Home > Article > Web Front-end > Dynamically binding HTML_html/css_WEB-ITnose
In Web front-end development, we often encounter the need to dynamically bind some HTML strings from the backend or dynamically spliced to the page DOM for display, especially in content management systems (CMS). : is the abbreviation of Content Management System), such needs are everywhere.
Readers of angular will definitely think of ngBindHtml first. Yes, angular provides us with this instruction to dynamically bind HTML. It will bind the calculated expression result to the DOM using innerHTML. However, the problem is not that simple. In Web security, XSS (Cross-site scripting, script injection attack) is a typical computer security vulnerability in Web applications. XSS attacks refer to injecting executable client code into web pages and successfully executing them by the browser to achieve the purpose of the attack, forming an effective XSS attack. Once the attack is successful, it may obtain some sensitive information of the user. Changing the user experience, inducing users and other illegal behaviors, sometimes XSS attacks are combined with other attack methods, such as SQL injection attacks on servers and databases, Click hijacking, relative link hijacking, etc. to implement phishing. The harm it brings is huge, and it is also a web The number one enemy of security. For more web security issues, please refer to the wiki https://en.wikipedia.org/wiki/Cross-site_scripting.
In angular, the added HTML content is not trusted by default. For the added HTML content, you must first use $sce.trustAsHtml to tell angular that this is trusted HTML content. Otherwise you will get $sce:unsafe exception error.
Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.
The following is a demo that binds a simple angular link:
HTML:
JavaScript:
angular.module("com.ngbook.demo", []) .controller("DemoCtrl", ["$sce", function($sce) { var vm = this; var html = 'hello angular'; vm.html = $sce.trustAsHtml(html); return vm; }]);
For simple static HTML, this problem is solved. But for complex HTML, complexity here refers to HTML templates with angular expressions and instructions. For them, we not only hope to bind large DOM displays, but also hope to get angular's powerful two-way binding mechanism. ngBindHhtml will not be associated with $scope for two-way binding. If there are ngClick, ngHref, ngSHow, ngHide and other angular instructions in HTML, they will not be compiled. Clicking these buttons will not cause any reaction. The expression of binding The formula will not be updated. For example, if you try to change the last link to: ng-href="demo.link", the link will not be parsed, and the original HTML string will still be seen in the DOM.
To take effect, all instructions in angular need to go through compile. Compile contains pre-link and post-link, and is connected to specific behaviors before they can work. In most cases, compile will be automatically compiled when angular starts. But if it is a dynamically added template, you need to compile manually. Angular provides us with the $compile service to implement this function. The following is a more general compile example:
HTML:
change
JavaScript:
angular.module("com.ngbook.demo", []) .directive("dyCompile", ["$compile", function($compile) { return { replace: true, restrict: 'EA', link: function(scope, elm, iAttrs) { var DUMMY_SCOPE = { $destroy: angular.noop }, root = elm, childScope, destroyChildScope = function() { (childScope || DUMMY_SCOPE).$destroy(); }; iAttrs.$observe("html", function(html) { if (html) { destroyChildScope(); childScope = scope.$new(true); var content = $compile(html)(scope); root.replaceWith(content); root = content; } scope.$on("$destroy", destroyChildScope); }); } }; }]) .controller("DemoCtrl", [function() { var vm = this; vm.html = '
'; vm.link = 'https://angular.io/'; var i = 0; vm.change = function() { vm.html = '
'; }; }]);