Transclude 函数需要正确修改 clone

Transclude function needs to modify clone properly

我有一个简单的指令,它重复一段嵌入的内容两次。像这样。

link: function (scope, element, attrs, controller, transclude) {

    transclude(scope.$parent, function(clone) {
        element.find('[transclude-main]').replaceWith(clone);
    });

    transclude(scope.$parent, function(clone) {
        element.find('[transclude-overflow]').replaceWith(clone);
    });

});

这主要按预期工作,但如果内容包含一个表单,那么我最终会得到两个同名的表单。

更重要的是,我的主页控制器(客户)仅引用其中一种形式(customers.myForm),因此如果我尝试重置该形式或调用任何其他形式控制器功能,则只有一种形式发生变化, 显然.

因此,我尝试修改我的代码以查找表单并将表单名称更改为新名称,如下所示。

link: function (scope, element, attrs, controller, transclude) {

    transclude(scope.$parent, function(clone) {
        element.find('[transclude-main]').replaceWith(clone);
    });

    transclude(scope.$parent, function(clone) {

        clone.find('FORM').each(function() {
            $(this).attr('name', $(this).attr('name') + '2');
        });
        element.find('[transclude-overflow]').replaceWith(clone);

    });

});

这确实为我修改了 HTML,我最终得到了两个表单 - myForm 和 myForm2。

问题是在我的主控制器中仍然只有一个对 myForm 的引用。第一个有效,但第二个无效。我只能假设它们是以某种方式针对 scope.$parent 编译的,在我弄乱克隆之前我将其传递给 transclude 函数?如果是这种情况,我不确定如何解决它。

编辑:

在这里添加了一个plunkr:

https://plnkr.co/edit/XE7REjJRShw43cpfJCh2

如果您打开一个开发控制台,您会看到我正在使用 console.log 写出 myForm 和 myForm2 的内容,它们应该是我第二个工具栏中表单的两个副本。 myForm2 不存在,我怀疑这是因为它是在克隆之前针对父作用域编译的。

所以这里有一个 plunkr with I thinnnk 得到你想要做的事情:https://plnkr.co/edit/8VxNPVmeLNLKyaQNReM3?p=preview

请特别注意这些行:

HTML:

  <toolbar name="myForm" form-one="myForm1" form-two="myForm2">
    <form name="myForm" submit="appController.submit()">
      Search:<br />
      <input type="text" ng-model="appController.searchText" />
    </form>
  </toolbar>

请注意,两个 name 属性都指向同一个字符串 "myForm"form-oneform-two 是正常的双向绑定,可以绑定到您选择的范围属性,在我的示例中,myForm1myForm2.

JS:

两种方式的绑定定义

    scope: {
      formOne: '=',
      formTwo: '='
    },

并将两个新表单绑定到各自的范围属性:

    link: function (scope, element, attrs, controller, transclude) {

        var parent = scope;

        transclude(function(clone, scope) {
            element.find('[transclude-main]').replaceWith(clone);
            var unwatch = scope.$watch(attrs.name, function(form) {
              if (form) {
                parent.formOne = form;
                unwatch();
              }
            });
        });

        transclude(function(clone, scope) {
            element.find('[transclude-overflow]').replaceWith(clone);
            var unwatch = scope.$watch(attrs.name, function(form) {
              if (form) {
                parent.formTwo = form;
                unwatch();
              }
            });
        });

回顾你的代码,这个控制台 console.log("myForm", $scope.myForm2) 打印了 undefined 因为 angular form 指令 are not dynamic. As a result, manually finding the html element and changing the name from myForm to myForm2 will not change the name of the form bound to scope unless the html has yet to be compiled. But the clone passed to transclude has been freshly compiled.