angularjs,$编译模板和ng-repeat

时间:2015-08-12 06:27:48

标签: angularjs compilation ng-repeat directive

基本上,我在一个指令的编译函数中使用了两个模板。 我在指令的编译阶段一次性编译它们(通过$ compile)。 在指令的链接阶段,我观察范围变量并将一个或另一个编译模板应用于范围。

testApp.directive('testField', ['$compile', function ($compile) {
  return {
    restrict: 'E',
    scope: true,
    compile: function(tElement, tAttrs) {
      var viewFn = $compile("<div>View: <span ng-repeat='x in [1,2,3]'>{{x}}</span></div>");
      var editFn = $compile("<div>Edit: <span ng-repeat='x in [4,5,6]'>{{x}}</span></div>");

      return function (scope, element, attrs) {
        var innerScope = null;

        scope.$watch("mode", function (mode) {
          if (innerScope) innerScope.$destroy();
          innerScope = scope.$new();

          if (mode == 'VIEW') {
              element.empty().append(viewFn(innerScope));
          } else {
              element.empty().append(editFn(innerScope));
          }
        });
      };
    }
  };
}]);

它工作正常,除非模板包含一个不是根元素的Ng-repeat,在这种情况下它表现得很奇怪:

要重现,请转到http://plnkr.co/edit/RCqlNWTVdXVoMQCkFcQn?p=preview 并从编辑到视图切换一些时间。

您会注意到ng-repeat的迭代次数会随着时间的推移而增长。 第一次,它显示123和456,就像它应该

在第一次来回查看和编辑之后,它显示123123和456456

每次在视图和编辑之间来回切换时,它都会不断添加一次迭代。

2 个答案:

答案 0 :(得分:1)

我可能在发布后不久就找到了解决方案。

问题显然在于ng-repeat需要克隆模板。

在角度源中发表评论后,我们可以将第二个参数传递给compile返回的函数。

第二个参数是一个函数,它通过模板的克隆(以及链接到的范围)来调用。

所以而不是

      if (mode == 'VIEW') {
          element.empty().append(viewFn(innerScope));
      } else {
          element.empty().append(editFn(innerScope));
      }

我能做到

      function setElts(elts) {
         element.empty().append(elts);
      }

      if (mode == 'VIEW') {
        viewFn(innerScope, setElts);
      } else {
        editFn(innerScope, setElts);
      }

答案 1 :(得分:1)

也许你可以做this

首先,您在视图中直接注入新的dom。之后,抓住它并应用$ compile。

像这样;

var viewFn = "<div>View: <span ng-repeat='x in [1,2,3]'>{{x}}</span></div>";
...
element.html(viewFn);
...
$compile(tElement.contents())(innerScope);