使用Angular 1.0.7:
我有一个用于显示样式复选框的指令。
有时 (并非总是)我的观察者不会更新我的范围变量之一,请参阅:
这是一个失败的序列:
我想知道为什么更新不会发生。
答案 0 :(得分:2)
你有一些你不需要的代码。一些代码,不完全确定哪一行,是干扰。主要是,当您在模板中设置ng-model='model'
时,您不需要在复选框上手动设置模型,这就是您所需要的!
所以这里是您的代码的工作分叉版本:http://plnkr.co/edit/CzhiAVEAuDtiL2QO95Za并且您可以看到我删除了与模型相关的几乎所有内容,因为它全部是自动的。
让我们总结一下我们做了什么:
简化指令代码:
app.directive("uuCheckbox", function() {
return {
restrict: "A",
transclude: true,
scope: {
model: '=',
clicked: '&'
},
template: "<div ng-click='select()'>" +
"<span ng-class='{ checked: model }'></span>" +
"<input class='hidden' value='true' type='checkbox' ng-model='model'>" +
"<span ng-class='{red: model}' ng-transclude></span>" +
"</div>",
compile: function(elmt, tAttrs) {
return function($scope, element, attrs) {
element.find('input').attr('name', attrs.name);
var on_change = function(new_value) {
$scope.clicked({ value: new_value });
};
$scope.$watch('model', on_change);
$scope.select = function() {
$scope.model = !$scope.model;
};
};
}
};
});
答案 1 :(得分:2)
这是一个非常有趣的问题,因此点击处理程序和 preferences.email 组合的问题出现了问题:
angularjs代码:
//https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js line 4510
scope.$watch(function parentValueWatch() {
var parentValue = parentGet(parentScope);
if (parentValue !== scope[scopeName]) {
// we are out of sync and need to copy
if (parentValue !== lastValue) {
// parent changed and it has precedence
lastValue = scope[scopeName] = parentValue;
} else {
// if the parent can be assigned then do so
parentSet(parentScope, parentValue = lastValue = scope[scopeName]);
}
}
return parentValue;
});
break;
您首先点击 foo + bar ,然后点击:
all: true
foo: true
bar: true
点击切换所有:
//by this code
var new_val = toggled_input_value();
$scope.model = new_val;
$ scope.model来自上面的代码是范围[scopeName] ,因此范围[scopeName] = false和lastValue = true,parentValue = true(它们将在$ digest运行后更改)< / p>
$scope.clicked({ value: new_val });
将致电
$scope.toggleAll = function(new_value){
if (new_value){
$scope.preferences.email.foo = true;
$scope.preferences.email.bar = true;
}
else{
$scope.preferences.email.foo = false;
$scope.preferences.email.bar = false;
}
}
所以,
all: true - $digest have not been run
foo: false
bar: false
并且,开始$ digest ...第一个电话将是:
$scope.$watch('preferences.email', function(new_value){
var bool = new_value.foo && new_value.bar;
$scope.preferences.all = bool;
}, true);
所以,
all: false
foo: false
bar: false
这是一个问题,因为在下一个 parentValueWatch 调用中我们会得到:
parentValue = false //$scope.preferences.all
scope[scopeName] = false //$scope.model
lastValue = true
所以, parentValue === scope [scopeName] ,并且lastValue尚未更新......这是一个错误:)
当您将$ scope.preferences.all更改为true时,您将获得
$scope.preferences.all === lastValue //true
并致电
// if the parent can be assigned then do so
parentSet(parentScope, parentValue = lastValue = scope[scopeName]);
所以,$ scope.preferences.all将变为false,而不是真正的
你可以在这里查看http://plnkr.co/edit/YEHqA101YwWKDvK6odFf?p=preview(console.trace)