Получение MathJax для обновления после изменений в модели AngularJS

Я пытаюсь использовать текст двустороннего связывания AngularJS, который включает в себя уравнения стиля латекса. Я хотел бы назвать MathJax для форматирования уравнений, но я не уверен в том, что MathJax вызывается после того, как AngularJS закончит изменение модели. Я думаю, мне нужен обратный вызов. Вот мой JavaScript:

var myApp = angular.module('myApp',[]); function MyCtrl($scope) { $scope.Update = function() { $scope.Expression = 'Evaluate: \\( \\frac{9}{4} \\div \\frac{1}{6} \\)'; MathJax.Hub.Queue(["Typeset", MathJax.Hub]); } $scope.Expression = 'Evaluate: \\( \\frac{5}{4} \\div \\frac{1}{6} \\)'; 

}

И вот мой HTML:

 
{{Expression}}

Fiddle здесь: http://jsfiddle.net/LukasHalim/UVjTD/1/ . Вы заметите, что на скрипке исходное выражение не удаляется даже после нажатия кнопки обновления дважды – кажется ошибкой или конфликтом.

Потеряв много дней (и, возможно, недель), сражаясь с MathJax, я слишком хорошо знаком с его различными причудами с обновлением математических выражений на лету. Я совершенно новый для Angular, но это дало мне хороший шанс погрузиться, и я закончил с решением, которое решает мои проблемы – надеюсь, он также решит вашу проблему.

Демо-версия: http://jsfiddle.net/spicyj/YpqVp/


Вместо использования простой интерполяции, которую предоставляет Angular, я создал новую директиву, основанную на ng-bind называемую mathjax-bind .

Если expression представляет собой переменную, содержащую математический код, то вместо \( {{expression}} \) вы можете написать:

  

и все будет набираться и обновляться в соответствующее время.

Поддерживающий код для директивы следует:

 myApp.directive("mathjaxBind", function() { return { restrict: "A", controller: ["$scope", "$element", "$attrs", function($scope, $element, $attrs) { $scope.$watch($attrs.mathjaxBind, function(texExpression) { var texScript = angular.element(" 

Простейшее, быстрое и стабильное решение:

 $rootScope.$watch(function(){ MathJax.Hub.Queue(["Typeset",MathJax.Hub]); return true; }); 

Преимущества:

  • Простота настройки, просто скопируйте этот код.
  • Все на вашей странице набирается.
  • Он работает намного быстрее, чем другие решения . Это связано с тем, что он может отображать страницу за один раз. Другие ответы здесь ждут завершения одного элемента, пока они не наберут следующий. Это делает рендеринг рендеринга медленным, если есть, например, несколько директив mathjax-bind (как предлагает другой ответ). Этот момент является причиной того, что я искал другой ответ.
  • Вы все же можете легко исключить элементы, используя опцию «ignoreClass» в настройках mathjax.

Бенчмаркинг: 100 директив mathjax-bind заняли 63 секунды , в то время как для этого метода потребовалось 1,5 секунды для отображения страницы. Я знаю, что эта функция будет выполняться много, так как она вызывается для каждого цикла дайджеста, однако она заметно не замедляет страницу.

Я создал простую скрипку, расширяющую ответ Бен Алперта. Вот скрипка и плунж .

В частности, если текст имеет только часть его, который должен быть преобразован Mathjax, вы можете использовать это. Для встроенного mathjax вы должны окружить текст символом $, а для отображения блока вы должны окружить блок на $$. (Вы можете использовать любой формат, который вам нравится, если вы создадите соответствующее регулярное выражение)

app.js

 MathJax.Hub.Config({ skipStartupTypeset: true, messageStyle: "none", "HTML-CSS": { showMathMenu: false } }); MathJax.Hub.Configured(); var myApp = angular.module("myApp", []); myApp.directive("mathjaxBind", function() { return { restrict: "A", scope:{ text: "@mathjaxBind" }, controller: ["$scope", "$element", "$attrs", function($scope, $element, $attrs) { $scope.$watch('text', function(value) { var $script = angular.element(" 

index.html

     AngularJS Plunker        

style.css

 input[type="text"] { width: 800px; } .red{ color:red; display:inline-block; } .blue{ color:blue; display:block; } 

Вот директива, которая позволяет использовать двойную курчавую разметку внутри выражения (и не требует установки переменной выражения в области). Он основан на этом сообщении в блоге , за исключением того, что я поддерживаю только MathJax, и я сохраняю скомпилированную DOM, чтобы он обновлял изменения переменных области.

Как сказал Алекс Осборн, лучше всего отделить математику от математики.

Применение:

 

This is inline math: x^{ {{power}} }, and this is display math:

y^{ {{power}} } .

В fragmentе:

 angular.module('app', []) .controller('ctrl', function($scope) { $scope.power = "\\sin(x^2)"; }) .directive('latex', function() { return { restrict: 'AE', link: function(scope, element) { var newDom = element.clone(); element.replaceWith(newDom); var pre = "\\(", post = "\\)"; if (element[0].tagName === 'DIV') { pre = "\\["; post = "\\]"; } scope.$watch(function() { return element.html(); }, function() { console.log(element); newDom.html(pre + element.html() + post); MathJax.Hub.Typeset(newDom[0]); }); } } }); 
   

Power:

This is the inline latex, x^{ {{power}} }, followed by some display mode latex

y^{ {{power}} } = {{power}}.
And that's it!

Простым решением является использование $ timeout для размещения MathJax.Hub.Queue(["Typeset", MathJax.Hub]) в очереди событий браузера (см. Запуск директивы после завершения рендеринга DOM ).

Что-то вроде этого:

  var app = angular.module('myApp', []); app.controller('myController', function ($scope, $timeout) { controller = this; $scope.Update = function () { $scope.value = " \\( \\frac{5}{4} \\div \\frac{1}{6} \\)"; $timeout(controller.updateMathJax, 0); } this.updateMathJax = function () { MathJax.Hub.Queue(["Typeset", MathJax.Hub]); } }); 

Взгляните на http://jsfiddle.net/pz5Jc/

В вашем шаблоне:

  {{Label}} {{Expression}} 

В вашем controllerе:

 $scope.Update = function() { $scope.Expression = '\\frac{9}{4} \\div \\frac{1}{6}'; $scope.Label = 'Updated Expression:' var math = MathJax.Hub.getAllJax("mathElement")[0]; math.Text('\\frac{4}{4} \\div \\frac{2}{6}'); } 

Пара пунктов:

Я не слишком хорошо знаком с mathjax, но:

  • Выделение метки из выражения позволяет работать с выражением напрямую.
  • Вам нужно вручную выбрать элемент DOM, чтобы принудительно обновить выражение. Это не очень «угловой» способ сделать что-то несчастливо, но когда mathjax анализирует выражение (и вставляет его собственные элементы DOM), он толкает эти элементы за пределы угловых привязок.
  • Исправить здесь – это выбрать правильный элемент mathjax и вызвать функцию изменения текста для обновления выражения.

Вы можете попробовать с моими изменениями http://jsfiddle.net/bmma8/4/ изменить ввод или нажать кнопку, чтобы обновить ваше выражение.

ЯШ:

 MathJax.Hub.Config({ extensions: ["tex2jax.js"], jax: ["input/TeX","output/HTML-CSS"], tex2jax: {inlineMath: [["$","$"],["\\(","\\)"]]} }); var myApp = angular.module('myApp',[]); function MyCtrl($scope, $log) { var QUEUE = MathJax.Hub.queue; // shorthand for the queue $scope.Update = function() { QUEUE.Push(["Text",MathJax.Hub.getAllJax("MathOutput")[0],"\\displaystyle{"+ $scope.Expression+"}"]); //$scope.Expression = 'Updated Expression: \\( \\frac{9}{4} \\div \\frac{1}{6} \\)'; //MathJax.Hub.Queue(["Typeset", MathJax.Hub]); } $scope.Expression = 'Original Expression: \\( \\frac{5}{4} \\div \\fra 

и html:

  
You typed: ${}$

Александр

Я действительно думал о другом решении. Когда вы делаете некоторые угловые и математические вы делаете это:

УГОЛЬНЫЙ КОНТРОЛЛЕР

 $scope x = 5; 

HTML

 

{{ '$ Multiplication = '+ x + ' * 2 =' + (x*2) + '$'}}

Сформированный результат Math Jax

Умножение = 5 * 2 = 10

Ключ должен включать знаки доллара в скобках в виде текста. Когда Angular делает их, знаки доллара будут отображаться как обычный текст, но когда формат Math Jax вступит в действие, он распознает знаки доллара и совершит волшебство.

Я строю директиву для этого ….

FIDDLE: http://jsfiddle.net/8YkUS/1/

HTML

p data-math-exp data-value = “math”>

JAVASCRIPT

  appFlipped.directive("mathExp", function () { return { scope: { value: "=" }, link: function (scope, el) { var domEl = el[0]; scope.$watch("value", function (newValue) { //nothing to do here if (newValue == null || window.MathJax == null)return; //update the dom with the new value and pass the hub for styling the equation domEl.innerHTML = '`' + newValue + '`'; MathJax.Hub.Queue(["Typeset", MathJax.Hub, domEl]); }); } } }); 

Я немного поработал над решением Рони. Отображение математики должно отображаться в режиме отображения; с

  

Я добавил атрибут сгенерированного диапазона, чтобы указать это.

Fiddle здесь http://jsfiddle.net/repa/aheujhfq/8/

  • Можете ли вы изменить путь без перезагрузки controllerа в AngularJS?
  • Невозможно найти подходящую версию для установки углового крепления
  • Угловая JS: Какова потребность в функции ссылки директивы, когда у нас уже есть controller директивы с объемом?
  • AngularJs ReferenceError: $ http не определен
  • Как получилось, что Angular не обновляется здесь?
  • «Непринятая ошибка: » с угловым после развертывания
  • Чтение заголовков ответов при использовании $ http Angularjs
  • AngularJS ng-options создают диапазон
  • AngularJS: Сервис против поставщика и завода
  • Устранение угловых «10 $ digest () итераций достигнуто« Ошибка
  • AngularJS - Использование $ index в ng-options
  • Давайте будем гением компьютера.