5

I have more or less simple html-pages with mathematical formulas which are rendered by MathJax. I am building now a new system using AngularJS, starting from the angular-seed. All individual html-files are included as partials. As expected, MathJax renders correctly only if I refresh the page, when I load it trough the framework, the Math-Expressions are not rendered.

I have to run this function somewhere:

MathJax.Hub.Queue(["Typeset",MathJax.Hub]);

It should run after each load of a partial to render the formulas correctly. How can I do this?

M

2 Answers 2

0

After struggling with the same problem you've described, I've found a quick if somewhat inelegant solution: include a second copy of MathJax.Hub.Queue(["Typeset",MathJax.Hub]);. For example here's part of my controller, where I want to have MathJax re-typeset after updating the scope:

function selectLesson(name){
        $scope.page = name.Path;
        if(!$mdMedia('gt-md')){
            $scope.toggleSideNav('left');
        }
        MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
        MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
    }

Because MathJax loads asynchronously (check out the MathJax Doc) , running MathJax.Hub.Queue(["Typeset",MathJax.Hub]); will wait until the page reloads to re-typeset the page. Running the same command again causes the typeset to occur immediately.

Sign up to request clarification or add additional context in comments.

Comments

0

I'd suggest using a directive triggered by an attribute. So your HTML would look like:

<span eqn-bind="$F = ma$"></label>

and your directive:

.directive('eqnBind', function () {
    return {
        restrict: "A",
        controller: ["$scope", "$element", "$attrs", function ($scope, $element, $attrs) {

            // Use this if it's a one-time thing and you don't need to re-render equations once they've been
            // inserted into the DOM.
            var value = $scope.$eval($attrs.esduEqnBind);
            $element.html(value);
            MathJax.Hub.Queue(["Reprocess", MathJax.Hub, $element[0]]);
            
            /*
            // Use this if you need to re-render eqns that already exist on the page or are going to need constant updates
            $scope.$watch($attrs.eqnBind, function (value) {
                $element.html(value);
                MathJax.Hub.Queue(["Reprocess", MathJax.Hub, $element[0]]);
            });
            */
        }]
    };
})

The second (commented out) part of the directive is more-or-less the same as this answer from 'Getting MathJax to update after changes to AngularJS model'.

The first part doesn't require a $watch so should be a bit more efficient.

As an aside - I've discovered katex, which seems much lighter and quicker. Using katex the above becomes:

.directive('eqnBind', function () {
    return {
        restrict: "A",
        controller: ["$scope", "$element", "$attrs", function ($scope, $element, $attrs) {

            // Use this if it's a one-time thing and you don't need to re-render equations once they've been
            // inserted into the DOM.
            var value = $scope.$eval($attrs.eqnBind);
            $element.html(value);
            renderMathInElement($element[0], { delimiters: [{ left: "$", right: "$", display: false }] });

            /*
            // Use this if you need to re-render eqns that already exist on the page...
            $scope.$watch($attrs.eqnBind, function (value) {
                $element.html(value);
                renderMathInElement($element[0], {delimiters:[{ left: "$", right: "$", display: false }]});
            });
            */
        }]
    };
})

2 Comments

How to use this inside ng-repeat?
@RAMESHKUMAR. It should just work. I use it inside ng-repeats.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.