从数据库编译动态 HTML 字符串

情况

在我们的 Angular 应用程序中嵌套了一个名为 Page 的指令,该指令由一个控制器支持,其中包含一个带有 ng-bind-html 不安全属性的 div。这被分配给一个名为“ pageContent”的 $scope 变量。这个变量从数据库中动态生成 HTML。当用户切换到下一个页面时,将对 DB 进行调用,并将 pageContent 变量设置为这个新的 HTML,该变量将通过 ng-bind-HTML-safe 在屏幕上呈现。密码是这样的:

页面指令

angular.module('myApp.directives')
.directive('myPage', function ($compile) {


return {
templateUrl: 'page.html',
restrict: 'E',
compile: function compile(element, attrs, transclude) {
// does nothing currently
return {
pre: function preLink(scope, element, attrs, controller) {
// does nothing currently
},
post: function postLink(scope, element, attrs, controller) {
// does nothing currently
}
}
}
};
});

Page 指令的 template (上面 templateUrl 属性中的“ Page.html”)

<div ng-controller="PageCtrl" >
...
<!-- dynamic page content written into the div below -->
<div ng-bind-html-unsafe="pageContent" >
...
</div>

页面控制器

angular.module('myApp')
.controller('PageCtrl', function ($scope) {


$scope.pageContent = '';


$scope.$on( "receivedPageContent", function(event, args) {
console.log( 'new page content received after DB call' );
$scope.pageContent = args.htmlStrFromDB;
});


});

这样就行了。我们可以在浏览器中很好地看到来自数据库的页面 HTML。当用户翻到下一页时,我们看到下一页的内容,依此类推。目前为止还不错。

问题

这里的问题是,我们希望在页面内容中包含交互式内容。例如,HTML 可能包含一个缩略图,当用户点击它时,Angular 应该做一些很棒的事情,比如显示一个弹出模式窗口。我已经在我们数据库的 HTML 字符串中放置了 Angular 方法调用(ng-click) ,但是当然 Angular 不会识别任何方法调用或指令,除非它以某种方式解析 HTML 字符串,识别它们并编译它们。

在我们的尸体上

第一页内容:

<p>Here's a cool pic of a lion. <img src="lion.png" ng-click="doSomethingAwesone('lion', 'showImage')" > Click on him to see a large image.</p>

第二页内容:

<p>Here's a snake. <img src="snake.png" ng-click="doSomethingAwesone('snake', 'playSound')" >Click to make him hiss.</p>

回到 Page 控制器中,然后添加相应的 $scope 函数:

页面控制器

$scope.doSomethingAwesome = function( id, action ) {
console.log( "Going to do " + action + " with "+ id );
}

我不知道如何从数据库的 HTML 字符串中调用‘ doSomething Awesome’方法。我意识到 Angular 必须以某种方式解析 HTML 字符串,但是如何解析呢?我读到过关于 $edit 服务的含糊不清的说法,并且复制和粘贴了一些示例,但是没有一个是有效的。此外,大多数示例显示只在指令的链接阶段设置动态内容。我们希望佩奇在整个应用程序的生命周期中都能活着。当用户翻页时,它不断地接收、编译和显示新内容。

在一个抽象的意义上,我想你可以说,我们正在试图动态嵌套的角度块在一个角度应用程序,并需要能够交换他们进出。

我曾多次阅读各种各样的 Angular 文档,以及各种各样的博客文章,还有 JS Fiddle with people’s code。我不知道我是否完全误解了 Angular,或者只是错过了一些简单的东西,或者也许我太慢了。无论如何,我需要一些建议。

159179 次浏览

ng-bind-html-unsafe仅将内容呈现为 HTML。它不会将 Angular 作用域绑定到生成的 DOM。为此,必须使用 $compile服务。我创建 这个傻瓜是为了演示如何使用 $compile创建由用户输入并绑定到控制器作用域的指令呈现动态 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>';
}

在角度1.2.10中,行 scope.$watch(attrs.dynamic, function(html) {返回了一个无效的字符错误,因为它试图观察 attrs.dynamic的值,它是 html 文本。

我通过从 scope 属性获取属性来修复这个问题

 scope: { dynamic: '=dynamic'},

我的榜样

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

在谷歌讨论组里找到的,我觉得行。

var $injector = angular.injector(['ng', 'myApp']);
$injector.invoke(function($rootScope, $compile) {
$compile(element)($rootScope);
});

你可以用

N- 绑定-html https://docs.angularjs.org/api/ng/service/$sce

指令动态绑定 html。 然而,您必须通过 $sce 服务获取数据。

请看现场演示在 http://plnkr.co/edit/k4s3Bx

var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,$sce) {
$scope.getHtml=function(){
return $sce.trustAsHtml("<b>Hi Rupesh hi <u>dfdfdfdf</u>!</b>sdafsdfsdf<button>dfdfasdf</button>");
}
});


<body ng-controller="MainCtrl">
<span ng-bind-html="getHtml()"></span>
</body>

尝试下面的代码通过 attr 绑定 html

.directive('dynamic', function ($compile) {
return {
restrict: 'A',
replace: true,
scope: { dynamic: '=dynamic'},
link: function postLink(scope, element, attrs) {
scope.$watch( 'attrs.dynamic' , function(html){
element.html(scope.dynamic);
$compile(element.contents())(scope);
});
}
};
});

尝试使用这个 element.html (scope.Dynamic) ; (attr.Dynamic) ;