Compiling Dynamic HTML Strings from Database

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>';
}

Compile dynamic HTML and bind variable from JSON response - Directive with Isolated scope - AngularJS

When you receive the JSON data you can use angular.fromJSON to decode the json string into the array (unless you are using the $http.get() which already does that for you)...

//request the JSON from server
jsonString = SomeFactory.fetchDataFromServer();
$scope.dataArray = angular.fromJson(jsonString);

...and then use the ngRepeat to create multiple elements:

<div ng-repeat="element in dataArray" dynamic="element"></div>

Modify your directive like this:

  app.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
link: function (scope, ele, attrs) {
scope.bindData = {};
scope.$watch(attrs.dynamic, function(dynamic) {
console.log('Watch called');
ele.html(dynamic.htmlTemplate); //here's your htmlTemplate being compiled
$compile(ele.contents())(scope);
scope.bindData = dynamic.bindData; //here's your bound data ifyou need the reference
scope.name = dynamic.bindData.name; //bound data property name
}, true); //deep watch
}
};
});

Edit: Or you could simply pass element.htmlTemplate and element.bindData separately to the directive through two separate attributes as mentioned in an answer by user Vineet, which makes more sense.
Edit2: Fixed some bugs.

Here's the fiddle: Fiddle

Angularjs dynamic html string compilation with an directive included inside

I have figured out the problem!! Assiging scope.ctrl with ctrl resolves the issue of not updating modalctrl.form
Plunker with working solution: http://plnkr.co/edit/ovz2RJDmnHPgLUqUaH7M

model.directive('dynamicInput', ['$compile', '$sce',
function($compile, $sce) {
return {
templateUrl: 'myContent.html',
require: '^ngController',
restrict: 'EA',
link: function(scope, element, attrs, ctrl) {
scope.ctrl = ctrl;
var html = '<content-input name=' + attrs.name + '></content-input>';
scope.html = $sce.trustAsHtml(html);
}
};
}
]);

dynamic html in angular js

In angular you have to tell the application that the HTML can be trusted.

https://docs.angularjs.org/api/ng/service/$sce

In the HTML you should set a html variable like:

<div ng-bind-html="htmlFromDB"></div>

in the controller you would use $sce

$scope.htmlFromDB = $sce.trustAsHtml(//somehtml)

This can be super dangerous, and add vulnerabilities to Cross site scripting. So make sure you know where that HTML came from!



Related Topics



Leave a reply



Submit