使用 AngularJS 将 HTML 插入并解析到视图中 [英] Insert and parse HTML into view using AngularJS
问题描述
我知道当我想将 HTML 插入视图时,我使用 'ng-bind-html'
或 'ng-bind-html-unsafe'
.
我不知道的是如何插入 HTML 并使 Angular 解析其内容
即如果有'ng-repeat'
,我想让Angular解析它?
更新 1:
示例:
HTML:
<div ng-repeat="t in ts" ng-bind-html-unsafe="t.html()"></div>
JS:
function Controller($scope) {$scope.ts = {obj1: new obj(), obj2: new obj(), ob3: new obj()};}函数对象(){//这可能是<div ng-repeat="s in somthing">{{s}}</div>"//或<ul><li ng-repeat="s in somthing">{{s.k}}</li></ul>"//或者是其他东西var_html;this.html = 函数(){返回_html;}}
我尝试使用上述方法,但 Angular 只是按原样打印 {{s}}
或 {{s.k}}
.
您可以使用 $compile
服务 (文档).
app.run(function($rootScope, $compile, $rootElement) {//我们将创建一个新范围用作视图的上下文.$scope = $rootScope.$new();$scope.model = [{name: 'first'}, {name: 'second'}, {name: 'third'}];//调用 `$compile(html)` 返回一个函数,当调用时//一个上下文对象,将编译后的 HTML 链接到给定的上下文(例如//将视图中基于作用域的表达式绑定到传入的作用域).var html = "<div ng-repeat='m in model'>{{m.name}}</div>";var linkingFunction = $compile(html);var elem = linkingFunction($scope);//然后您可以像平常一样使用 DOM 元素.$rootElement.append(elem);});
在本例中,我已将视图附加到 $rootElement
(引导模块时使用的元素,通常由 ng-app
指示);在许多情况下,您将在指令的链接函数中执行此类操作,并且可以访问相关元素.当然,您可以使用 jQuery 或 jqLite 获取原始 HTML,但请记住在执行此操作之前在链接的作用域上至少允许一个摘要循环(否则 HTML 将尚未使用作用域中的值进行更新).
工作示例:http://jsfiddle.net/BinaryMuse/QHhVR/
在 ng-include
指令的内部,Angular 正在做这件事:
$compile(currentElement.contents())(currentScope);
<小时>
[更新]
这是一个更完整的示例,它演示了更接近您更新的问题的内容:
app.controller("MainController", function($scope) {$scope.ts = [{元素:['一','二','三'],html: '<div ng-repeat="elem in t.elements">{{elem}}</div>'},{事情:[8, 9, 10],添加:功能(目标){var last = target[target.length - 1];target.push(last + 1);},html: '<ul><li ng-repeat="num in t.things">{{num}}</li>'+'<li><button ng-click="t.add(t.things)">更多</button></li></ul>'}];});app.directive("bindCompiledHtml", function($compile, $timeout) {返回 {模板:'<div></div>',范围: {rawHtml: '=bindCompiledHtml'},链接:功能(范围,元素,属性){scope.$watch('rawHtml', function(value) {如果(!值)返回;//我们想使用这个指令的范围之外//(它本身是一个隔离范围).var newElem = $compile(value)(scope.$parent);elem.contents().remove();elem.append(newElem);});}};});
<div ng-repeat="t in ts" bind-compiled-html="t.html"></div>
工作示例:http://jsfiddle.net/BinaryMuse/VUYCG/
HTML 片段使用 t.elements
和 t.things
毫无价值,因为 t
是由ng-repeat
在 outer HTML 中.如果你愿意,你可以做一些范围体操来让这个更好一点.
What I know is when I want to insert HTML into view, I use 'ng-bind-html'
or 'ng-bind-html-unsafe'
.
What I don't know, is how to insert HTML and make Angular parse its content
i.e. if there is 'ng-repeat'
, I want Angular to parse it?
Update 1:
example:
HTML:
<div ng-repeat="t in ts" ng-bind-html-unsafe="t.html()"></div>
JS:
function Controller($scope) {
$scope.ts = {obj1: new obj(), obj2: new obj(), ob3: new obj()};
}
function obj() {
// which may be "<div ng-repeat="s in somthing">{{s}}</div>"
// or "<ul><li ng-repeat="s in somthing">{{s.k}}</li></ul>"
// or something else
var _html;
this.html = function() {
return _html;
}
}
I tried using the above, but Angular just print {{s}}
or {{s.k}}
as it is.
You can compile arbitrary HTML into an angular view with the $compile
service (docs).
app.run(function($rootScope, $compile, $rootElement) {
// We'll create a new scope to use as the context for the view.
$scope = $rootScope.$new();
$scope.model = [{name: 'first'}, {name: 'second'}, {name: 'third'}];
// Calling `$compile(html)` returns a function that, when called with
// a context object, links the compiled HTML to the given context (e.g.
// binds scope-based expressions in the view to the passed in scope).
var html = "<div ng-repeat='m in model'>{{m.name}}</div>";
var linkingFunction = $compile(html);
var elem = linkingFunction($scope);
// You can then use the DOM element like normal.
$rootElement.append(elem);
});
In this case, I've attached the view to the $rootElement
(which is the element that was used when bootstrapping the module, usually by the ng-app
directive); in many cases, you'll do this kind of thing in a directive's linking function and will have access to the element in question. You can, of course, get the raw HTML using jQuery or jqLite, but remember to allow at least one digest cycle on the linked scope before you do so (or else the HTML won't yet have been updated with values from the scope).
Working example: http://jsfiddle.net/BinaryMuse/QHhVR/
Down in the bowels of the ng-include
directive, Angular's doing this very thing:
$compile(currentElement.contents())(currentScope);
[Update]
Here is a more complete example that demonstrates something a bit closer to your updated question:
app.controller("MainController", function($scope) {
$scope.ts = [
{
elements: ['one', 'two', 'three'],
html: '<div ng-repeat="elem in t.elements">{{elem}}</div>'
},
{
things: [8, 9, 10],
add: function(target) {
var last = target[target.length - 1];
target.push(last + 1);
},
html: '<ul><li ng-repeat="num in t.things">{{num}}</li>' +
'<li><button ng-click="t.add(t.things)">More</button></li></ul>'
}
];
});
app.directive("bindCompiledHtml", function($compile, $timeout) {
return {
template: '<div></div>',
scope: {
rawHtml: '=bindCompiledHtml'
},
link: function(scope, elem, attrs) {
scope.$watch('rawHtml', function(value) {
if (!value) return;
// we want to use the scope OUTSIDE of this directive
// (which itself is an isolate scope).
var newElem = $compile(value)(scope.$parent);
elem.contents().remove();
elem.append(newElem);
});
}
};
});
<div ng-controller="MainController">
<div ng-repeat="t in ts" bind-compiled-html="t.html"></div>
</div>
Working example: http://jsfiddle.net/BinaryMuse/VUYCG/
It's worth nothing that the HTML snippets use t.elements
and t.things
because t
is the scope value that is created by the ng-repeat
in the outer HTML. You could do some scope gymnastics to make this a bit nicer if you like.
这篇关于使用 AngularJS 将 HTML 插入并解析到视图中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!