I’m new to Angularjs and the Dojo-Toolkit so please forgive my newbieness.
I have an element in my page that I’m able to bind to my model without any problem: <input type="text" ng-model="startDateRange"></input> This works as expected.
When I update the element so it uses the Dojo-Toolkit the binding appears to be broken: <input type="text" ng-model="startDateRange" data-dojo-type="dijit/form/DateTextBox"></input> The binding to the model no longer works.
I’m not sure what I’m doing wrong. Any help would be appreciated. Thanks.
AngularJS binding works upon DOM nodes, if you move, delete or replace a DOM node that AngularJS is watching, then the code will no longer work.
As Thomas Kagan said, Dojo widgets will replace the DOM node with the data-dojo-type on it by the DOM nodes provided in the template of those widgets. This simply erases your binding as if it didn't exist.
A proper AngularJS solution would be to wrap the Dojo DateTextBox inside a directive, so AngularJS knows that this is encapsulated and AngularJS should only access the directive through an API (the scope of a directive).
For example:
myApp.directive("dateTextBox", function($timeout) {
var link = function(scope, elem, attr) {
require(["dijit/form/DateTextBox"], function(DateTextBox) {
var dateTxtBox = new DateTextBox({});
dateTxtBox.set('value', scope.date);
dateTxtBox.on("change", function(date) {
$timeout(function() {
scope.date = date;
});
});
elem.append(dateTxtBox.domNode);
});
};
return {
restrict: 'E',
scope: {
date: "="
},
link: link
};
});
This is just a basic example, I also made a demo, which you can view by running the snippet below.
angular.module("myApp", []).controller("TestCtrl", function($scope) {
$scope.date = new Date();
})
.directive("dateTextBox", function($timeout) {
var link = function(scope, elem, attr) {
require(["dijit/form/DateTextBox"], function(DateTextBox) {
var dateTxtBox = new DateTextBox({});
dateTxtBox.set('value', scope.date);
dateTxtBox.on("change", function(date) {
$timeout(function() {
scope.date = date;
});
});
elem.append(dateTxtBox.domNode);
});
};
return {
restrict: 'E',
scope: {
date: "="
},
link: link
};
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dijit/themes/claro/claro.css" />
<script src="//ajax.googleapis.com/ajax/libs/dojo/1.10.1/dojo/dojo.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.min.js"></script>
<script src="script.js"></script>
</head>
<body ng-app="myApp" class="claro">
<div ng-controller="TestCtrl">
<date-text-box date="date"></date-text-box><br />
{{date | date}}
</div>
</body>
</html>
When the dojo parser runs it will identify the input element as a dijit widget and destroy your input element replacing it with a dojo widget so the ng-model property will no longer be present. I recommend using Dojo's observable module for data-binding instead of trying to mix in angular
Related
I'm trying to automatically create an instance of 'loadPlugCtrl'
as may times as directive is used, but it's not working. You can see it's
printing the same label twice where as they should be different.
One more thing I noticed that in directive the command
console.log(ctrlInstName);
is getting executed only once. I have no idea what's happening here.
// Code goes here
angular.module('plunker', ['loadPlugin']);
function randomString(length) {
chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var result = '';
for (var i = length; i > 0; --i) result += chars[Math.floor(Math.random() * chars.length)];
return result;
}
angular.module('loadPlugin', [])
.directive("loadPlugin", ['$compile', function($compile){
var ctrlInstName = "loadPluginCtrl_" + randomString(8);
console.log(ctrlInstName);
return{
restrict: 'E',
replace: true,
controller: "loadPluginCtrl",
controllerAs:ctrlInstName,
link: function(scope, element, attrs) {
scope.label = randomString(attrs.plug);
var template = '<p>{{label}}</p>';
var linkFn = $compile(template);
var content = linkFn(scope);
element.append(content);
} // End link
}; // End return
}])
.controller("loadPluginCtrl", ['$scope', function($scope) {
// This controller should be instantiated as many times
// as the directive is used in HTML.
}]);
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<link rel="stylesheet" href="style.css">
<script data-require="angular.js#1.6.x" src="https://code.angularjs.org/1.6.4/angular.js" data-semver="1.6.4"></script>
<script src="script.js"></script>
</head>
<body>
<p>Test</p>
<load-plugin plug="15"></load-plugin>
<load-plugin plug="20"></load-plugin>
</body>
</html>
Let me explain you guys, what actually I am trying to do.
I have n number of form templates stored on server along with their data in
database. All most all of the features required to handle forms has been written in a controller. Let's say it's a base controller for all of them.
Load the form template dynamically along with it's data using GET service.
Automatically assign base controller's instance to it.
I am aware of the face that Angular is designed for SPA but my requirement is more of website like. I was wrong when thought I could achieve this using directive.
I would be glad if some one point me the right direction to do.
A controller is instantiated each time when a directive is compiled, this is what it is for.
The problem is that you picked the wrong way to test this. Directive factory function is executed only once. That's why ctrlInstName never changes. All controller-specific code should be put to controller.
Dynamic controllerAs property is not possible and is a design mistake.
Each instance of directive will create a new controller instance.... but there is only one registration of the directive itself within the module
If you use controllerAs you want to assign values to the controller object not $scope and there is no benefit in creating a dynamic controller alias name:
angular.module('loadPlugin', [])
.directive("loadPlugin", ['$compile', function($compile) {
return {
restrict: 'E',
replace: true,
controller: "loadPluginCtrl",
//scope: {},
template: '<p>{{$ctrl.label}}</p>',
controllerAs: '$ctrl',
link: function(scope, element, attrs, ctrl) {
ctrl.label = randomString(attrs.plug);
} // End link
}; // End return
}])
.controller("loadPluginCtrl", ['$scope', function($scope) {
var vm = this;
// demonstrate that each use creates own instance of controller
$scope.$watch(function(){
return vm.label;
}, function(nVal) {
if (nVal) {
console.log('Label for this instance is:', nVal)
}
})
}]);
DEMO
i am trying to implement block-ui into our angular application on an element by element basis. (everything is included, referenced and injected correctly)
We have been trying to implement
block-ui-pattern
with no success.
our $http request is :-
$http.get('/user/123/GetUserAddress/').then(function (data) {
and our block-ui-pattern is :-
< div block-ui block-ui-pattern="/^user\/123\/GetUserAddress\$/">
{{address}}
</div>
This seems to match the documentation, but is failing to work. Am i missing something fundamental?
Our application exposes an isloading flag. initially set to true, and when the $http promise returns, sets this to false.. I realize that it is not in the documentation, however, Is there a way to set
< div block-ui="isloading"></div>
Post by Parash Gami pointed me in the right direction.
I actually ended up writing a custom directive that wraps block-ui
var myBlocker = angular.module('app.Angular.Directive.myBlocker ', []);
myBlocker.directive('myBlocker ', ['$compile', function ($compile) {
return {
restrict: 'A',
scope :{
blockId: '#id',
block: '=',
},
controller: ['$scope', 'blockUI', function ($scope, blockUI) {
var myBlock = blockUI.instances.get($scope.blockId);
$scope.$watch('block', function (newValue, oldValue) {
if ($scope.block === true)
{
myBlock.start()
}
else {
myBlock.stop()
}
});
}],
link: function link(scope, element, attrs) {
element.attr('block-ui', scope.blockId);
element.attr('style', 'min-height:200px;');
element.removeAttr("my-blocker");
element.removeAttr("data-my-blocker");
$compile(element)(scope);
}
};
}]);
This allows me to now simply add the directive to an element
< div id="myId" my-blocker block="loading">
Please check sample code. Just include one CSS and one JS of blockUI and add dependency blockUI, use blockUI.start() method to show loader and use blockUI.stop() method to hide loader. Following example hide loader after 2 seconds. Use it as per your requirement.
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="http://angular-block-ui.nullest.com/angular-block-ui/angular-block-ui.css">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular.min.js"></script>
<script type="text/javascript" src="http://angular-block-ui.nullest.com/angular-block-ui/angular-block-ui.js"></script>
</head>
<body ng-app="app.user">
<div ng-controller="tempController">
</div>
</body>
</html>
<script type="text/javascript">
var app = angular.module('app.user',['blockUI']);
app.controller('tempController', function(blockUI,$timeout)
{
blockUI.start();
$timeout(function()
{
blockUI.stop();
},2000)
});
</script>
I can't figure out what's wrong with my code. I'm following the example of this fiddle in order to bind the two inputs. What I'm trying to do is just a little more involved- I'd like to load a certain template based on an attribute passed into the directive. I can't figure out what's wrong over here.
This is my html
<!-- template -->
<script type="text/ng-template" id="X-template.html">
<button ng-click='clickMe()'><b>Check model</b></button>
Directive: <input ng-model="this.test"></input>
</script>
<div ng-controller="MyCtrl">
<my-directive type="X"></my-directive>
No Directive:<input ng-model="this.test"></input>
{{this.test}}
</div>
And my JS:
var app = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.this= {test : "asdf"};
$scope.clickMe = function() {
alert($scope.this.test);
}
}
app.directive('myDirective', function() {
return {
restrict: 'E',
compile: function(element, attrs) {
element.append('<div ng-include="\'' + attrs.type + '-template.html\'"></div>');
}
}
});
The issue is with trying to use this, which is a reserved keyword in JavaScript, as a property name.
Try using a different property name. I changed your example to use foo in the link below.
http://jsfiddle.net/01h3ne4y/
If you are working with Angular, probably you will have case where you want to call some JQUERY library to do something for you. The usual way would be to call JQUERY function on page ready:
$(function(){
$(element).someJqueryFunction();
});
If your element content is dynamically added using Angular, than this approach is not good as I understood, and you need to create an custom directive in order to fulfill this functionality.
In my case, I want to load bxSlider on <ul class="bxslider"> element, but content of the <ul> element should be loaded using angular ng-repeat directive.
Picture names are collected using REST service from the database.
I call my directive called startslider using the following code:
<div startslider></div>
My custom Angular directive is: (pictures is variable in the $scope passed from my controller, which called REST service)
application.directive('startslider', function () {
return {
restrict: 'A',
replace: false,
template: '<ul class="bxslider">' +
'<li ng-repeat="picture in pictures">' +
'<img ng-src="{{siteURL}}/slide/{{picture.gallery_source}}" alt="" />'
'</li>' +
'</ul>',
link: function (scope, elm, attrs) {//from angular documentation, the link: function should be called in order to change/update the dom elements
elm.ready(function () {
elm.bxSlider({
mode: 'fade',
autoControls: true,
slideWidth: 360,
slideHeight:600
});
});
}
};
});
As result, I get all the pictures from the database displayed on my screen, but without bxSlider loaded (all pictures displayed one bellow other).
Please note that bxSlider is working, because when I call $(element).bxSlider(); on manually written code, the slider loads.
Why is this happening?
EDIT:
I think your problem is caused by trying to call the slider on HTMLUListElement, which is an object.
To call the slider on the DOM element, you could use $("." + $(elm[0]).attr('class')) that will use the existing bxslider class, or better assign an id to your <div startslider id="slideshow"></div> and call like $("." + $(elm[0]).attr('id'))
elm.ready(function() {
$("." + $(elm[0]).attr('class')).bxSlider({
mode: 'fade',
autoControls: true,
slideWidth: 360,
slideHeight:600
});
});
Full code:
http://jsfiddle.net/z27fJ/
Not my solution, but I'd thought I would pass it along.
I like this solution the best (Utilizes directive controllers)
// slightly modified from jsfiddle
// bxSlider directive
controller: function() {},
link: function (scope, element, attrs, controller) {
controller.initialize = function() {
element.bxSlider(BX_SLIDER_OPTIONS);
};
}
// bxSliderItem directive
require: '^bxSlider',
link: function(scope, element, attrs, controller) {
if (scope.$last) {
controller.initialize();
}
}
http://jsfiddle.net/CaioToOn/Q5AcH/8/
Alternate, similar solution, using events (I do not like)
Jquery bxslider not working + Angular js ng-repeat issue
Root issue
You cannot call scope.$apply in the middle of a digest cycle.
You cannot fire bxSlider() until the template gets compiled.
Ultimately, you need to wait for the template to be compiled and available before calling bxSlider()
Calling a function when ng-repeat has finished
this is the directive
.directive('slideit', function () {
return function (scope, elm, attrs) {
var t = scope.$sliderData;
scope.$watch(attrs.slideit, function (t) {
var html = '';
for (var i = 0; i <= t.length-1; i++) {
html += '<li><ul class="BXslider"><li class="BXsliderHead"><img src="'+scope.$imageUrl+'flight/'+t[i].code+'.gif" />'+t[i].name+'</li><li class="BXsliderChild">'+t[i].noneStop+'</li><li class="BXsliderChild">'+t[i].oneStop+'</li><li class="BXsliderChild">'+t[i].twoStop+'</li></ul></li>';
}
angular.element(document).ready(function () {
$("#" + $(elm[0]).attr('id')).html(html).bxSlider({
pager:false,
minSlides: 3,
maxSlides: 7,
slideWidth: 110,
infiniteLoop: false,
hideControlOnEnd: true,
auto: false,
});
});
});
};
});
this is the html in view
<div ui-if="$sliderData">
<ul id="experimental" slideit="$sliderData"></ul>
</div>
and the important part is the dependency of js file
<script src="/yii-application/frontend/web/js/libraries/angular/angular.min.js"></script>
<script src="/yii-application/frontend/web/js/libraries/angular/angular-ui.js"></script>
<script src="/yii-application/frontend/web/js/libraries/jquery/jquery-1.11.3.min.js"></script>
<script src="/yii-application/frontend/web/js/libraries/flex/jquery.bxslider.min.js"></script>
<script src="/yii-application/frontend/web/assets/e3dc96ac/js/bootstrap.min.js"></script>
<script src="/yii-application/frontend/web/js/libraries/jquery-ui/jquery-ui.min.js"></script>
<script src="/yii-application/frontend/web/js/searchResult.js"></script>
<script src="/yii-application/frontend/web/js/Flight.js"></script>
and don't forget to put ui in module
var app = angular.module('myApp', ['ui']);
this is the bxslider that i use !!!! maybe solve your problem
I am trying to use AngularJS two-way binding text which includes Latex style equations. I would like to call MathJax to format the equations, but I'm not sure of the best way to ensure that MathJax is called after AngularJS finishes changing the model. I think I need a callback. Here is my 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} \\)';
}
And here is my HTML:
<div ng-controller="MyCtrl">
<button ng-click="Update()">Update</button>
{{Expression}}
</div>
Fiddle is here: http://jsfiddle.net/LukasHalim/UVjTD/1/. You'll notice that on the fiddle the original expression isn't removed even after you click the update button twice - seems like a bug or conflict.
Having wasted many days (and maybe weeks) fighting MathJax, I'm all too familiar with its various quirks with updating math expressions on the fly. I'm brand new to Angular but this gave me a good chance to dive in and I ended up with a solution which solves my problems -- hopefully it'll solve yours as well.
Live demo: jsfiddle
Instead of using the plain interpolation that Angular provides, I created a new directive based on ng-bind called mathjax-bind.
If expression is a variable containing math code, then instead of \( {{expression}} \) you can write:
<span mathjax-bind="expression"></span>
and everything will be typeset and updated at the appropriate times.
The supporting code for the directive follows:
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("<script type='math/tex'>")
.html(texExpression ? texExpression : "");
$element.html("");
$element.append(texScript);
MathJax.Hub.Queue(["Reprocess", MathJax.Hub, $element[0]]);
});
}]
};
});
Simplest, fastest and most stable solution:
$rootScope.$watch(function(){
MathJax.Hub.Queue(["Typeset",MathJax.Hub]);
return true;
});
Advantages:
Easy to setup, just copy this code.
Everything on your page is typeset.
It renders much faster than the other solutions. This is because it can render the page in one go. Other answers here wait for one item to finish, until they typeset the next one. That makes rendering veeeery slow if there are for example multiple mathjax-bind directives (as another answer suggests). This point is the reason I was looking for a different answer.
You can still easily exclude elements using the option “ignoreClass” in your mathjax settings.
Benchmarking:
100 mathjax-bind directives took 63 seconds, while with this method it took 1.5 second to render the page. I know that this function will be executed a lot since it's called on every digest cycle, however, it doesn't noticeably slow down the page.
I created a simple fiddle expanding on Ben Alpert's answer. Here's the fiddle and plunk.
Specifically If a text has only a part of it to be converted by Mathjax, you can use this.
For inline mathjax you must surround the text by $, and for block display you must surround the block by $$. (You can use any format you like if you create the corresponding regex)
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("<script type='math/tex'>")
.html(value == undefined ? "" : value);
$element.html("");
$element.append($script);
MathJax.Hub.Queue(["Reprocess", MathJax.Hub, $element[0]]);
});
}]
};
});
myApp.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
html = html.replace(/\$\$([^$]+)\$\$/g, "<span class=\"blue\" mathjax-bind=\"$1\"></span>");
html = html.replace(/\$([^$]+)\$/g, "<span class=\"red\" mathjax-bind=\"$1\"></span>");
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
function MyCtrl($scope, $element) {
$scope.html = "A coin of is $ \\frac{5}{4} $ thrown $$\\frac{1}{6}$$ dfv";
}
index.html
<!DOCTYPE html>
<html ng-app="myApp">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<script src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML&delayStartupUntil=configured&dummy=.js"></script>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.2.x" src="http://code.angularjs.org/1.2.7/angular.js" data-semver="1.2.7"></script>
<script src="app.js"></script>
</head>
<body>
<div ng-controller="MyCtrl">
<input type="text" ng-model="html"/><br/>
<div dynamic="html"></div>
</div>
</body>
style.css
input[type="text"] {
width: 800px;
}
.red{
color:red;
display:inline-block;
}
.blue{
color:blue;
display:block;
}
Take a look at http://jsfiddle.net/pz5Jc/
In your template:
{{Label}} <span id="mathElement">{{Expression}}</span>
In your 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}');
}
Couple of points:
I'm not too familiar with mathjax, but:
Splitting the label out from the expression allows you to work with the expression directly.
You need to manually pick up a DOM element to force a refresh of the expression. This isn't a very 'angular' way to do things unfortunately - but when mathjax parses the expression (and inserts it's own DOM elements), it pushes those elements outside the angular bindings.
Fix here is to specifically select the correct mathjax element and call a text change function to update the expression.
Here's a directive that lets you use double curly markup inside the expression (and doesn't require setting an expression variable on the scope). It's based on this blog post, except I only support MathJax, and I save the compiled DOM, so that it updates on changes to scope variables.
As Alex Osborn said, it's best to separate non-math from math.
Usage:
<p>This is inline math: <latex>x^{ {{power}} }</latex>,
and this is display math: <div latex> y^{ {{power}} } .</div></p>
In a snippet:
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]);
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<div ng-app="app" ng-controller="ctrl">
<p>Power:
<input ng-model="power" />
</p>
<p>This is the inline latex,
<latex>x^{ {{power}} }</latex>, followed by some display mode latex
<div latex>y^{ {{power}} } = {{power}}.</div>And that's it!
</p>
</div>
A simple solution is to use $timeout to put MathJax.Hub.Queue(["Typeset", MathJax.Hub]) in the browser event queue (see Run a directive after the DOM has finished rendering).
Something like this:
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]);
}
});
You can try with my modifications http://jsfiddle.net/bmma8/4/
modify input or click on button will update your expression.
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
and html:
<div ng-controller="MyCtrl">
<button ng-click="Update()">Update</button>
<input ng-model="Expression" ng-change="Update()">
<div id="MathOutput">
You typed: ${}$
</div>
</div>
Alexandre
I actually thought of another solution. When you render some angular and math you do this:
ANGULAR CONTROLLER
$scope x = 5;
HTML
<h3> {{ '$ Multiplication = '+ x + ' * 2 =' + (x*2) + '$'}} </h3>
Formated Math Jax result
Multiplication = 5 * 2 = 10
The key is to include the dollar signs inside the brackets as text. When Angular renders them, the dollar signs will appear as plain text, but when the Math Jax format comes into action it will recognize the dollar signs and do the magic.
I Build a directive for this....
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]);
});
}
}
});
I fiddled a bit more on Roney's solution. The display math should be displayed in display mode; with
<script type="math/tex; mode=display">
I added an attribute to the generated span to indicate that.
Fiddle is here http://jsfiddle.net/repa/aheujhfq/8/