双向绑定不能在指令中使用transcluded作用域

我有一个控制器中的文本框绑定到模型name 。 控制器内有一个指令,指令里面还有另一个文本框,它绑定到同一个模型name

 <div class="border" ng-controller="editCtrl"> Controller: editCtrl <br/> <input type="text" ng-model="name" /> <br/> <tabs> Directive: tabs <br/> <input type="text" ng-model="name"/> </tabs> </div> 

 mod.directive('tabs', function() { return { restrict: 'E', transclude: true, template: '<div class="border" ng-transclude></div>', }; }); 

当您在外部文本框中input内容时,它会反映在内部文本框中,但是如果在内部文本框中键入内容,它将停止工作,即两个文本框不会再反映相同的值。

看例子: http : //jsfiddle.net/uzairfarooq/MNBLd/

我也尝试过使用两种方式绑定attr( scope: {name: '='} ),但它给语法错误。并使用scope: {name: '@'}具有相同的效果。

任何帮助将不胜感激。

除了被接受的答案之外, 这篇文章还真的帮助我理解了孩子们的原型inheritance。 我强烈build议任何有问题的人都可以仔细阅读。

带有transclude: true的指令transclude: true导致指令创build一个新的(transcluded)子作用域。 这个新的范围原型从父范围inheritance。 在你的情况下,父范围是与editCtrl控制器关联的范围。

在子范围(即ng-model)中使用双向数据绑定来绑定到一个包含原始值(例如, name )的父范围属性总是会导致问题 – 呃,我应该说这不起作用预期。 当在子级中更改范围属性(例如,键入第二个文本框)时,子级创build一个新的范围属性,该范围属性隐藏/遮蔽同名的父范围属性。 如果父属性包含一个原始值, 则在创build子属性 ,该值(基本上)被复制到子属性。 子范围的未来更改(例如第二个文本框)只影响子属性。

在input第二个文本框之前(即,在子属性更改之前),子/跨行范围通过原型inheritance(下图中的虚线)在父范围中查找name属性。 这就是两个文本框最初保持同步的原因。 下面,如果您在第一个文本框中键入“标记”,这是范围如下所示:

传递范围遵循继承链

我创build了一个小提琴 ,你可以检查两个范围。 单击第二个文本框旁边的“显示范围”链接,然后键入第二个文本框。 这将允许您看到被横扫的子范围。 您将会注意到,此时它没有name属性。 清除控制台,键入第二个文本框,然后再次单击该链接。 您会注意到子范围现在有一个name属性,并且初始值是父属性具有的值(“标记”)。 如果您在第二个文本框中键入“喜欢angular”,这是范围如下所示:

transcluded原始隐藏父项属性

有两个解决scheme:

  1. 做什么@ pgreen2build议(这是“最佳实践”的解决scheme) – 使用一个对象,而不是原始的。 当一个对象被使用时,子/ transcluded作用域不会得到一个新的属性。 这里只有原型inheritance。 在下面的图片中,假设editCtrl的$ scope已经定义了这个对象:
    $scope.myObject = { name: "Mark", anotherProp: ... }
    在父母的对象
  2. 在子范围中使用$ parent(这是一个脆弱的解决scheme,不build议使用,因为它会对HTML结构进行假设):在<tabs>中的<input>内使用ng-model="$parent.name"元件。 上面的第一张图片显示了这是如何工作的

使用scope: {name: '='}时发生语法错误scope: {name: '='}因为当使用双向数据绑定时(即使用'='时),不允许插入 – 即不能使用{{}}。 而不是<tabs name="{{name}}">使用<tabs name="name">

使用'@'的作用与transclude相同,因为ng-transclude使用transcluded作用域,而不是使用scope: { ... }创build的隔离作用域。

有关范围(包括图片)的更多信息,请参阅
AngularJS中范围原型/原型inheritance的细微差别是什么?

我认为这个问题与范围界定有关。 内部文本框最初没有name设置,所以它从外部范围inheritance。 这就是为什么在外框中打字反映在内框。 但是,一旦在内部框中键入,内部范围现在包含name ,这意味着它不再绑定到外部name所以外部文本框不会同步。

适当的方法来解决只是在范围内存储模型,而不是你的价值观。 我在http://jsfiddle.net/pdgreen/5RVza/中解决了这个问题,就是创build一个模型对象(; data )并在其上引用值。

不正确的代码修改了指令中的作用域,正确的代码修改了指令作用域中的模型。 这种细微的差异使范围inheritance正常工作。

我相信MiškoHevery所说的方式是,范围应该是只写在控制器中, 只读在指令中。

更新:参考: https : //www.youtube.com/watch?v = ZhfUv0spHCY#t = 29m19s

语法错误意味着你误写了一些东西。 它与特定的框架/库无关。 你可能忘了添加“,”或closurespalenthesis。 再次检查出来