Ottenere MathJax da aggiornare dopo le modifiche al modello AngularJS

Sto cercando di utilizzare il testo di bind a due vie AngularJS che include le equazioni di stile Latex. Vorrei chiamare MathJax per formattare le equazioni, ma non sono sicuro del modo migliore per garantire che MathJax venga chiamato dopo che AngularJS ha completato la modifica del modello. Penso di aver bisogno di una richiamata. Ecco il mio 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} \\)'; 

}

Ed ecco il mio HTML:

 
{{Expression}}

Fiddle è qui: http://jsfiddle.net/LukasHalim/UVjTD/1/ . Noterai che sul violino l’espressione originale non viene rimossa anche dopo aver fatto clic due volte sul pulsante di aggiornamento: sembra un bug o un conflitto.

    Avendo perso molti giorni (e forse settimane) in lotta con MathJax, ho fin troppo familiarizzato con le sue varie stranezze con l’aggiornamento delle espressioni matematiche al volo. Sono nuovo di zecca per Angular ma questo mi ha dato una buona possibilità di immergermi e ho finito con una soluzione che risolve i miei problemi – speriamo che risolva anche il tuo.

    Demo dal vivo: http://jsfiddle.net/spicyj/YpqVp/


    Invece di usare la semplice interpolazione fornita da Angular, ho creato una nuova direttiva basata su ng-bind chiamato mathjax-bind .

    Se expression è una variabile che contiene il codice matematico, allora invece di \( {{expression}} \) puoi scrivere:

      

    e tutto sarà composto e aggiornato ai tempi appropriati.

    Il codice di supporto per la direttiva segue:

     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(" 

    La soluzione più semplice, più veloce e più stabile:

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

    vantaggi:

    • Facile da configurare, basta copiare questo codice.
    • Tutto sulla tua pagina è composto.
    • Rende molto più veloce rispetto alle altre soluzioni . Questo perché può rendere la pagina in una volta sola. Altre risposte qui aspettano che un object finisca, finché non compongono il prossimo. Questo rende il rendering veeeery lento se ci sono per esempio più direttive mathjax-bind (come suggerisce un’altra risposta). Questo punto è la ragione per cui stavo cercando una risposta diversa.
    • Puoi ancora escludere facilmente gli elementi usando l’opzione “ignoreClass” nelle tue impostazioni di mathjax.

    Benchmarking: 100 direttive mathjax-bind impiegavano 63 secondi , mentre con questo metodo ci volevano 1,5 secondi per rendere la pagina. So che questa funzione verrà eseguita molto poiché è chiamata su ogni ciclo di digestione, tuttavia, non rallenta notevolmente la pagina.

    Ho creato un semplice violino espandendo la risposta di Ben Alpert. Ecco il violino e il plunk .

    Specificamente, se un testo ha solo una parte di esso da convertire da Mathjax, puoi usare questo. Per mathjax in linea devi circondare il testo di $, e per la visualizzazione del blocco devi circondare il blocco di $$. (Puoi usare qualsiasi formato che ti piace se crei la regex corrispondente)

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

    Ecco una direttiva che consente di utilizzare il doppio markup riccio all’interno dell’espressione (e non richiede l’impostazione di una variabile di espressione sull’oscilloscopio). È basato su questo post del blog , tranne che supporto MathJax e salvo il DOM compilato, in modo che si aggiorni sulle modifiche alle variabili scope.

    Come ha detto Alex Osborn, è meglio separare i non matematici dalla matematica.

    Uso:

     

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

    y^{ {{power}} } .

    In un frammento:

     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!

    Una soluzione semplice consiste nell’utilizzare $ timeout per inserire MathJax.Hub.Queue(["Typeset", MathJax.Hub]) nella coda degli eventi del browser (consultare Esegui una direttiva dopo che il DOM ha completato il rendering ).

    Qualcosa come questo:

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

    Dai un’occhiata a http://jsfiddle.net/pz5Jc/

    Nel tuo modello:

      {{Label}} {{Expression}} 

    Nel tuo 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}'); } 

    Paio di punti:

    Non ho molta familiarità con MathJax, ma:

    • La divisione dell’etichetta dall’espressione consente di lavorare direttamente con l’espressione.
    • È necessario selezionare manualmente un elemento DOM per forzare un aggiornamento dell’espressione. Questo non è un modo molto “angular” di fare le cose purtroppo – ma quando mathjax analizza l’espressione (e inserisce i propri elementi DOM), spinge quegli elementi fuori dai collegamenti angolari.
    • Correggere qui è quello di selezionare specificamente l’elemento mathjax corretto e chiamare una funzione di modifica del testo per aggiornare l’espressione.

    Puoi provare con le mie modifiche http://jsfiddle.net/bmma8/4/ modificare l’input o fare clic sul pulsante per aggiornare la tua espressione.

    js:

     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 

    e html:

      
    You typed: ${}$

    Alexandre

    In realtà ho pensato ad un’altra soluzione. Quando rendi un po ‘angular e matematico, fai questo:

    CONTROLLORE ANGOLARE

     $scope x = 5; 

    HTML

     

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

    Risultato Math Jax formulato

    Moltiplicazione = 5 * 2 = 10

    La chiave è includere i segni del dollaro all’interno delle parentesi come testo. Quando Angular li esegue, i segni del dollaro appariranno come testo semplice, ma quando il formato Math Jax entrerà in azione riconoscerà i segni del dollaro e farà la magia.

    Costruisco una direttiva per questo ….

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

    Ho giocato un po ‘di più sulla soluzione di Roney. Il display matematico dovrebbe essere visualizzato in modalità display; con

      

    Ho aggiunto un attributo allo span generato per indicarlo.

    Fiddle è qui http://jsfiddle.net/repa/aheujhfq/8/