AngularJS:如果元素具有ngModel和具有本地作用域的指令,则双向数据绑定将失败

13

问题在这里显示:http://jsfiddle.net/ews7S/

<input type="text" ng-model="testModel" dir="123">

当一个元素在控制器作用域中绑定到模型,并且您还向该元素添加具有自己本地作用域的指令时,则对模型的更改仅在指令作用域中更改。


AngularJS + document.getElementById,我可以问一下为什么吗? - Liviu T.
angular.element('#out').text(scope.textModal) 是 AngularJS 的写法,但它会抛出一个错误,说“选择器未实现”。 - Atomix
至少从1.0.1版本开始,元素(id / class选择器)可用。 - Liviu T.
@Liviu,我在Atomix的fiddle中尝试了angular.element('#out')...,但它给出了“选择器未实现”的错误。也许只有在加载jQuery时才能使用。 - Mark Rajcok
啊,没错,可能是因为Angular的jQueryLite没有实现选择器。 - Liviu T.
2个回答

18

另一种解决方案是使用对象作为模型,而不是基本类型。然后新指令的作用域将继承(原型继承)对该对象的引用,而不是基本类型的值的副本:

$scope.model = { testProp: "444" };

<input type="text" ng-model="model.testProp" dir="123">
<input type="text" ng-model="model.testProp">

document.getElementById("out").innerHTML = scope.model.testProp;

http://jsfiddle.net/mrajcok/awfU5/

使用一个基本类型,如 $scope.testModel,指令作用域的 testModel 属性会获得父作用域的 testModel 的值的 副本。对其中一方进行更改不会影响另一方。

使用一个对象,如 $scope.model,父作用域和指令作用域都有对同一个(一个)对象的引用。对其中任何一方所做的更改都会影响同一个对象。

另一种(脆弱的)解决方案是使用未公开文档的 $parent 属性(对问题 fiddle 进行这些更改):

<input type="text" ng-model="$parent.testModel" dir="123">

document.getElementById("out").innerHTML = scope.$parent.testModel;

请注意,使用$parent是一种脆弱的解决方案,因为$parent的使用取决于DOM结构。例如,在父级和子级(现在变成孙子级)之间添加了另一个控制器(由您明确添加或由另一个Angular指令隐含添加),我们将需要使用$parent.$parent.testModel


这是一个很好的解释,为什么在某些情况下绑定到对象而不是原始类型非常重要。+1 - theMothaShip
我曾经遇到过一个文本区域的问题。第一种解决方案(继承对象的引用)有效,但第二种则无效!更准确地说:它在一段时间内有效,然后由于没有明显的原因而停止了。文本区域停止更新父级作用域属性。我建议避免使用$parent解决方案,它似乎非常不稳定和脆弱! - tivoni
@tivoni,它可能停止工作是因为使用$parent取决于DOM结构。如果在父级和子级(现在的孙子)之间添加了另一个控制器(由您明确添加或由另一个Angular指令隐式添加),则可能需要使用$parent.$parent.testModel。我会更新帖子以反映这一点。 - Mark Rajcok
@Mark 我确定在这两个控制器之间没有添加其他控制器。 - tivoni
你太棒了,马克...虽然基础,但这是一个非常重要的概念。 - Kings

6

1
这个解决方案还创建了一个“隔离作用域”,这与原问题中的“scope:true”不同。在问题fiddle中,“scope:true”创建了一个新的作用域,该作用域从父作用域原型继承。在此解决方案fiddle中,创建了一个新的作用域,该作用域不从父作用域原型继承。如果您想要一个新作用域原型继承的解决方案,请参见我的替代答案。如果您不想要继承(通常情况下不需要),那么这就是您想要的解决方案。 - Mark Rajcok
2
ngModel 拥有比其他简单属性更多的职责。因此,你也会遇到 NgModelController 的问题。当指令被链接时,ngModel.$viewValue/$modelValue 将不是你所需要的。 - Artem Andreev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接