我写了一个angularjs指令。 在这个指令的模板中,我添加了一个ngIf指令,在其中我显示了一个绑定到我的指令范围的输入。
<div ng-if="bool"><input ng-model="foo"></div>
我注意到,经过大量的试验和错误后,ngIf指令导致模型在输入文本更改时不会更新。如果我将它改为ngShow,一切都按预期工作。
我正在寻找这种差异的解释
答案 0 :(得分:29)
这是因为ngIf创建了一个新的子范围,所以如果你想绑定到与其他输入相同的范围,我们可以用$ parent向下一级。检查here以了解有关范围继承的更多信息
angular.module('testApp', [])
.directive('testDir', function () {
return {
restrict: 'A',
template: '<input ng-model="foo"><input ng-model="foo">' +
'<div ng-if="bool"><input ng-model="$parent.foo"></div>',
link: function (scope, elem, attrs) {
scope.foo = "bar";
scope.bool = true;
}
}
});
看看新的jsfiddle
答案 1 :(得分:20)
这是因为你在范围上使用了一个原语。
ngIf
创建一个新的子范围,它会遮蔽父范围的值。
<div ng-if="bool"><input ng-model="data.foo"></div>
范围继承通常很简单,你甚至不需要知道它正在发生......直到你尝试双向数据绑定(即表单元素,ng-model)到一个原语(例如,数字) ,string,boolean)在子范围内从父范围定义。
它不像大多数人预期的那样有效。会发生的是子作用域获取自己的属性,该属性隐藏/隐藏同名的父属性。这不是AngularJS正在做的事情 - 这就是JavaScript原型继承的工作原理。
新的AngularJS开发人员通常没有意识到 ng-repeat,ng-switch,ng-view和ng-include都创建了新的子范围,因此当涉及这些指令时,问题经常会出现。
通过遵循始终have a '.' in your ng-models的“最佳实践”,可以轻松避免使用原语这个问题。
答案 2 :(得分:2)
将foo定义为具有属性的对象。这一切都与javascript原型继承有关。查看修改后的jsfiddle。
angular.module('testApp', [])
.controller('MyController',function($scope){
$scope.foo = {bool: true};
})
.directive('testDir', function () {
return {
restrict: 'A',
template: '<input ng-model="foo.x"><input ng-model="foo.x"><div ng-if="foo.bool"><br/>changing me does not update the other inputs because i am in an ngIf if in ngShow all works just fine<input ng-model="foo.x"></div>',
link: function (scope, elem, attrs) {
scope.foo.x = "bar";
scope.foo.bool = true;
}
}
});
有关详细信息,请参阅此video。