AngularJS: Using $compile on html that contains directives with templateurl

佐手、 提交于 2019-11-30 09:53:15

As you probably realised, you need to call $scope.$apply() for it to update the {{bindings}} from the scope values.

But the reason you couldn't do it inside your async function was that you were compiling the HTML against the existing scope for #target, but then trying to append just the HTML. That won't work, because you need to have the compiled node in the DOM, either by appending the entire compiled node using jQuery's .append() or similar, or by setting the DOM innerHTML first, then compiling the node that is in the DOM. After that, you can call $apply on that scope and because the directive is compiled and in the DOM, it will be updated correctly.

In other words, change your async code as follows.

Instead of:

target.innerHTML = $compile(html)($scope)[0].outerHTML
$scope.$apply()

Change it to:

target.innerHTML = html;
$compile(target)($scope);
$scope.$digest();

Note that I did a $digest() instead of $apply(). This is because $apply() does a digest of every single scope, starting from the $rootScope. You only need to digest that one scope you linked against, so it is sufficient (and faster, for any reasonably sized app with lots of scopes) to just digest that one.

Forked fiddle

Update: Angular can compile strings and detached DOM nodes

I just checked, and the OP was actually correct in assuming that Angular can compile strings of HTML or detached DOM nodes just fine. But what you do need to do is make sure you actually append the compiled node to the DOM, not just the HTML. This is because Angular stores things like the scope and the binding information as jQuery/jQueryLite data on the DOM node*. Thus you need to append the whole node, with that extra information, so that the $digest() will work.

So an alternative way of having this work is to change the same portion of the OP's code as above to:

target.appendChild($compile(html)($scope)[0]);
$scope.$digest()

* Technically, it is stored in the internal jQuery data cache, with the cache key being stored on the DOM node itself.

Append the element to the target first, then compile it.

html = angular.element(html);
target = angular.element(target);
target.append(html);
html = $compile(html)($scope)

http://jsfiddle.net/f3dkp291/16/

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!