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="angular.js@1.0.7" 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>';}
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); }); } }; });
Found in a google discussion group. Works for me.
var $injector = angular.injector(['ng', 'myApp']);$injector.invoke(function($rootScope, $compile) { $compile(element)($rootScope);});