Обновить MathJax после загрузки нового представления в Angularjs

У меня есть более-менее простые html-страницы с математическими формулами, которые рендерит MathJax. Сейчас я создаю новую систему, используя AngularJS, начиная с angular-seed. Все отдельные html-файлы включены как частичные. Как и ожидалось, MathJax отображается правильно, только если я обновляю страницу, когда я загружаю ее через фреймворк, Math-Expressions не отображаются.

Я должен где-то запустить эту функцию:

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

Он должен запускаться после каждой загрузки партиала для правильного отображения формул. Как я могу это сделать?

M


person user3144995    schedule 30.12.2013    source источник


Ответы (2)


После борьбы с той же проблемой, которую вы описали, я нашел быстрое, хотя и несколько неэлегантное решение: включить вторую копию MathJax.Hub.Queue(["Typeset",MathJax.Hub]);. Например, вот часть моего контроллера, где я хочу повторно набрать MathJax после обновления области:

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]);
    }

Поскольку MathJax загружается асинхронно (ознакомьтесь с документацией по MathJax), выполнение MathJax.Hub.Queue(["Typeset",MathJax.Hub]); будет ждать, пока страница перезагружается для повторного набора страницы. Повторный запуск той же команды приводит к немедленному набору текста.

person gus    schedule 22.05.2015

Я бы предложил использовать директиву, активируемую атрибутом. Таким образом, ваш HTML будет выглядеть так:

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

и ваша директива:

.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]]);
            });
            */
        }]
    };
})

Вторая (закомментированная) часть директивы более или менее совпадает с этой ответ от 'Получение MathJax для обновления после изменений к модели AngularJS'.

Первая часть не требует $watch, поэтому должна быть немного более эффективной.

Кстати, я обнаружил katex, который кажется намного легче и быстрее. Используя katex, вышеприведенное становится:

.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 }]});
            });
            */
        }]
    };
})
person SAL    schedule 26.02.2016
comment
Как использовать это внутри ng-repeat? - person RAMESHKUMAR; 28.01.2019
comment
@РАМЕШКУМАР. Это должно просто работать. Я использую его внутри ng-repeats. - person SAL; 18.04.2021