Reputation: 392
I've created a filter in AngularJS 1.2 that uses the ShowdownJS to parse Markdown content into HTML:
App.filter('markdown', function( $sce ) {
var converter = new Showdown.converter();
return function (value) {
var html = converter.makeHtml(value);
return $sce.trustAsHtml(html);
};
});
The binding in the templates is done with ng-bind-html. This one receives to final HTML content so it's mandatory to show the content:
<div ng-bind-html="post.content | markdown"></div>
The filter works but I get this error in console because it returns the $sce service and it SHOULD return just the parsed HTML string.
10 $digest() iterations reached. Aborting!
How can I avoid this in a filter? I could not find any method that can can extract the escaped html from the $sce service.
EDIT: if I disable the sanitize service in the config I don't get this error even if the code remains exactly the same.
$sceProvider.enabled(false);
Upvotes: 4
Views: 6893
Reputation: 1499
When I had this error, I was accidentally using a filter on an object instead of a string.
Upvotes: 0
Reputation: 23664
Ok after some investigation I found that the problem is instances. Every time your filter fires you return another instance. Then the ng-bind-html watcher fires infinitely.
I added a cache of all trusted values:
app.filter('markdown', ['$sce', function( $sce ) {
var converter = new Showdown.converter();
var converted = {};
return function (value) {
if(converted.hasOwnProperty(value)) {
return converted[value];
}
var html = converter.makeHtml(value);
var trusted = converted[value] = $sce.trustAsHtml(html);
return trusted;
};
}]);
Upvotes: 3
Reputation: 29214
I think it has something to do with ngBindHtmlDirective watching it and calling $sce.getTrustedHtml on the value. You can get around it by avoiding $sce
and using your own directive (plnkr):
App.directive('simpleHtml', function() {
return function(scope, element, attr) {
scope.$watch(attr.simpleHtml, function (value) {
element.html(scope.$eval(attr.simpleHtml));
})
};
})
Upvotes: 1