问题
I have a bit of a problem. I have a directive
app.directive('a', function() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
elem.on('click', function(e){
e.preventDefault();
alert('Hyperlinks not allowed!');
});
}
};
});
and a $http
request for JSON
containing the page content
{
"currentNodeName":"Page 1",
"childrenNodes":[
{"id":"3","name":"Page 1-1"},
{"id":"4","name":"Page 1-2"}],
"parentNode":null,
"currentNodeContent":[
{"content":"<p>This is Page1. <a href=\"http://badlink.org/i/dont/want/to/work\">Link</a></p>"}],
"currentNodeId":"1"
}
The currentNodeContent
is loaded to a div
<div id="loadedContent" ng-bind-html="boardCtrl.nodeData.currentNodeContent[0].content"></div>
and now the question:
How can I achieve that the loaded content's <a>
tag works as a directive?
Thanks.
回答1:
an almost correct asnwer can be found at angular ng-bind-html and directive within it although a better form would be:
app.directive("unsecureBind", function($compile) {
return {
link: function(scope, element, attrs) {
scope.$watch(attrs.unsecureBind, function(newval) {
element.html(newval);
$compile(element.contents())(scope);
});
}
};
});
The ng-bind-html simply assigns the data to the html without running $compile on it (see https://github.com/angular/angular.js/blob/master/src/ng/directive/ngBind.js#L197 ). This still isn't completely right becouse on change of the value the contained directives are not notified that they are being destroyed a better version would therefore be.
app.directive("unsecureBind", function($compile) {
return {
link: function(scope, element, attrs) {
var childscope;
scope.$watch(attrs.unsecureBind, function(newval, oldval) {
if (!newval && !oldval) return; // handle first run
if (childscope)
childscope.$destroy();
element.html(newval || "");
if (!newval) return;
childscope = scope.$new();
$compile(element.contents())(childscope);
});
}
};
});
This is correct from the angular point of view, BUT:
- you are completely violating the idea of mvc
- by restricting the elements with directives you're basicaly blacklisting elements which is generaly not a good idea you should use a whitelist.
- It is also very insecure to allow user input be part of your angular running context.
it would be a better idea to filter the input html through a whitelist function and then bind that with ng-bind-html.
回答2:
Angular is using 'a' as a directive as priority '0' (https://docs.angularjs.org/api/ng/directive/a)
Try doing this:
- set your priority higher than what was defined, example 1 or Number.MAX_VALUE.
- set terminal to true, so it won't process the lower priorities.
could work, i guess... :)
来源:https://stackoverflow.com/questions/25507525/render-angularjs-directive-on-http-loaded-content