문제

I am using Angular UI Router with MathJax. When I route to a new state, the MathJax does not get processed. What burns my noodle is that if I have an update button with exactly the same code it works. Just not by itself.

PLUNKER

HTML

<p id="MathExample"><strong>Equation:</strong> {{data.equation}}</p>
<button class="btn btn-primary" ng-click="update()">Update</button>

JS

$stateProvider.state('route1', {
  url: "/route1",
  templateUrl: "route1.html",
  controller: function($scope, $http){

    $http({method: 'GET', url: 'data.json'})
    .success(function(data) {
      $scope.data = data;
       MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
       //You would think that the value would be updated here!
    })

    $scope.update = function($scope){
      MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
      //This works just fine, but is not automatic.
    }

  }
 });

I'm trying to figure out why this is the case. Do I need to use $apply? One question hinted at the use of a directive. However, I don't need this function. I really just need the JSON data with the math expressions to reliably become typeset.

도움이 되었습니까?

해결책

It looks like you just need to wait for the DOM to settle down before MathJax can process it. A simple setTimeout call seems to fix the issue:

$http({method: 'GET', url: 'data.json'})
.success(function(data) {
  $scope.data = data;
  setTimeout(function() {
    MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
  });
});

See http://plnkr.co/edit/xIVvUHntVZ7lftGz9cDn?p=preview for an example.


You mentioned using a directive; you could use one to abstract away the need to call the MathJax function manually at all.

In this example, I've created a directive called math that automatically lays out whatever's passed in with MathJax:

var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider, $urlRouterProvider){

  $urlRouterProvider.otherwise("/");//Was defaulting to route 1. No more

  $stateProvider.state('route1', {
      url: "/route1",
      templateUrl: "route1.html",
      controller: function($scope, $http, $timeout){
        $http({method: 'GET', url: 'data.json'})
        .success(function(data) {
          $scope.data = data;
        });
      }
  });

});

myapp.directive('math', function() {
  return {
    restrict: 'EA',
    scope: {
      math: '@'
    },
    link: function(scope, elem, attrs) {
      scope.$watch('math', function(value) {
        if (!value) return;
        elem.html(value);
        MathJax.Hub.Queue(["Typeset", MathJax.Hub, elem[0]]);
      });
    }
  };
});
<hr>
<h3>Route 1's data</h3>
<p>
  <strong>Name:</strong>
  {{data.name}}
</p>
<p>
  <strong>Equation:</strong>
  <span math="{{data.equation}}"></span>
</p>

See http://plnkr.co/edit/c9NBXXd9kF7Jne6saS3i?p=preview for a demonstration.

Going this route, absolutely anything passed to the math directive will be automatically rendered with MathJax whenever it changes. See this demo for an example that lets you edit the equation: http://plnkr.co/edit/dJSEGtBKSrKLjiwuLsl5?p=preview

다른 팁

Because you are trying to modify Math on the page before it is rendered. You can use the $timeout to wait until it is rendered:

var myapp = angular.module('myapp', ["ui.router"])
myapp.config(function($stateProvider, $urlRouterProvider){

  $urlRouterProvider.otherwise("/");//Was defaulting to route 1. No more

  $stateProvider.state('route1', {
      url: "/route1",
      templateUrl: "route1.html",
      controller: function($scope, $http, $timeout){
        $http({method: 'GET', url: 'data.json'})
        .success(function(data) {
          $scope.data = data;
          $timeout(function() {
            MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
          }, 0);
        })
        $scope.update = function($scope){
          MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
        }
      }
  });
});
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top