我在控制器中有一个绑定到模型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>',
};
});
当您在外部文本框中键入内容时,它会反映在内部文本框中,但如果您在内部文本框中键入某些内容,它将停止工作,即两个文本框不再反映相同的值。
请参阅示例:http://jsfiddle.net/uzairfarooq/MNBLd/
我也尝试过使用双向绑定attr(scope: {name: '='}
),但它会产生语法错误。使用scope: {name: '@'}
会产生同样的效果。
非常感谢任何帮助。
除了接受的答案外,this article确实帮助我理解了儿童scpoes的原型继承。我强烈建议任何有范围问题的人仔细阅读。
答案 0 :(得分:128)
带有transclude: true
的指令会导致指令创建一个新的(已转换的)子范围。这个新范围原型继承自父范围。在您的情况下,父作用域是与editCtrl控制器关联的作用域。
在子范围(即ng-model)中使用双向数据绑定绑定到包含原始值的父范围属性(例如name
)总会导致问题 - 我应该说它没有按预期工作。当子项中的scope属性发生更改时(例如,您键入第二个文本框),子项创建一个新的scope属性,该属性隐藏/隐藏同名的父scope属性。如果父属性包含原始值,则在创建子属性时(<本质)将该值复制到子属性 。子范围的未来更改(例如,第二个文本框)仅影响子属性。
在键入第二个文本框之前(即,在子项中更改属性之前),子/ transcluded范围通过原型继承(下图中的虚线)在父作用域中找到name
属性。这就是为什么两个文本框最初保持同步。下面,如果在第一个文本框中键入“Mark”,则这是范围的样子:
我创建了一个fiddle,您可以在其中检查这两个范围。在键入第二个文本框之前,单击第二个文本框旁边的“显示范围”链接。这将允许您查看已转移的子范围。您会注意到此时它没有name
属性。清除控制台,键入第二个文本框,然后再次单击该链接。您会注意到子范围现在具有name
属性,初始值是父属性具有的值(“Mark”)。如果您在第二个文本框中键入“喜欢Angular”,这就是范围的样子:
有两种解决方案:
$scope.myObject = { name: "Mark", anotherProp: ... }
:
ng-model="$parent.name"
在&lt; tabs&gt;内元件。上面的第一张图片展示了它是如何工作的。使用scope: {name: '='}
时会出现语法错误,因为在使用双向数据绑定时(即使用'='时),不允许插值 - 即不能使用{{}}。而不是<tabs name="{{name}}">
使用<tabs name="name">
。
使用'@'与transclude案例的工作原理相同,因为ng-transclude使用了被转换的范围,而不是使用scope: { ... }
创建的隔离范围。
关于(大量)有关范围(包括图片)的更多信息,请参见
What are the nuances of scope prototypal / prototypical inheritance in AngularJS?
答案 1 :(得分:10)
我认为这个问题与范围界定有关。最初,内部文本框没有设置name
,因此它继承自外部范围。这就是为什么在外框中输入反映在内框中的原因。但是,一旦在内框中输入内容,内部范围现在包含name
,这意味着它不再绑定到外部name
,因此外部文本框不会同步。
修复的适当方法是仅在范围内存储模型,而不是您的值。我在http://jsfiddle.net/pdgreen/5RVza/中修复了它。诀窍是创建一个模型对象(data
)并在其上引用值。
错误的代码修改了指令中的范围,正确的代码修改了指令范围内的模型。这种微妙的差异允许范围继承正常工作。
我相信MiškoHevery所说的方式,范围应该是控制器中的只写,并且指令中的只读。
答案 2 :(得分:0)
语法错误意味着你错误地写了一些东西。它与特定框架/库无关。您可能忘了添加“,”或关闭一个paranthesis。再看一遍