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

前端 未结 2 1656
温柔的废话
温柔的废话 2020-12-30 15:01

I have a legacy application that has some content inserted into the DOM via jQuery. I would like the legacy parts of the codebase to be responsible for compiling the html th

相关标签:
2条回答
  • 2020-12-30 15:32

    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.

    0 讨论(0)
  • 2020-12-30 15:34

    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/

    0 讨论(0)
提交回复
热议问题