Compiling dynamic HTML strings from database
ng-bind-html-unsafe
only renders the content as HTML. It doesn't bind Angular scope to the resulted DOM. You have to use $compile
service for that purpose. I created this plunker to demonstrate how to use $compile
to create a directive rendering dynamic HTML entered by users and binding to the controller's scope. The source is posted below.
demo.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="[email protected]" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
<script src="script.js"></script>
</head>
<body>
<h1>Compile dynamic HTML</h1>
<div ng-controller="MyController">
<textarea ng-model="html"></textarea>
<div dynamic="html"></div>
</div>
</body>
</html>
script.js
var app = angular.module('app', []);
app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.$watch(attrs.dynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);
});
}
};
});
function MyController($scope) {
$scope.click = function(arg) {
alert('Clicked ' + arg);
}
$scope.html = '<a ng-click="click(1)" href="#">Click me</a>';
}
Found in a google discussion group. Works for me.
var $injector = angular.injector(['ng', 'myApp']);
$injector.invoke(function($rootScope, $compile) {
$compile(element)($rootScope);
});
In angular 1.2.10 the line scope.$watch(attrs.dynamic, function(html) {
was returning an invalid character error because it was trying to watch the value of attrs.dynamic
which was html text.
I fixed that by fetching the attribute from the scope property
scope: { dynamic: '=dynamic'},
My example
angular.module('app')
.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
scope: { dynamic: '=dynamic'},
link: function postLink(scope, element, attrs) {
scope.$watch( 'dynamic' , function(html){
element.html(html);
$compile(element.contents())(scope);
});
}
};
});