我正在尝试扩展ngModel
,以便即使验证失败,我也会有$empty
标志。我们用它来显示“明文”按钮。
模型覆盖正常,但我注意到标志更改不会立即应用。调用$digest
会引发“进行中”错误。
myApp.directive('ngModel', function() {
return {
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
var checkEmpty = function() {
ngModel.$empty = (ngModel.$$rawModelValue === undefined ||
ngModel.$$rawModelValue.length === 0);
};
checkEmpty();
element.on('keyup', checkEmpty);
}
}
});
答案 0 :(得分:0)
您是否被迫使用keyup事件?为了避免与摘要时间有关的问题,您应该使用$viewChangeListeners来连接到ngModel的管道。
link: function(scope, element, attrs, ngModel) {
var checkEmpty = function() {
ngModel.$empty = (ngModel.$$rawModelValue === undefined || ngModel.$$rawModelValue.length === 0);
console.log(ngModel.$empty);
};
checkEmpty();
ngModel.$viewChangeListeners.push(checkEmpty);
// element.on('keyup', checkEmpty);
}
答案 1 :(得分:0)
嗯,我发现$timeout
有效,它会在下一个周期设置我的代码:
element.on('keyup', function() {
$timeout(checkEmpty);
});
答案 2 :(得分:0)
您只需$watch
进行更改并设置变量:
scope.$watch(function(){
return ngModel.$isEmpty(ngModel.$viewValue);
},
function(v){
ngModel.$empty = v;
})
编辑:
当然,这是低效的,因为它注册了$watch
。
正如评论中正确指出的那样,$viewChangeListeners
不会因无效输入而触发。绑定到元素事件也很糟糕,因为ng-model
应该与DOM无关。
可行的方法是注册首先运行的$parser
。这在大多数情况下都可以 - 但不能保证全部工作,因为任何其他指令都可以在我们的解析器之前(在任何时候)自由注册自己的解析器并在解析器之前使值无效有机会运行并重新设置$empty
。
priority: -100,
require: "ngModel",
link: function(scope, element, attrs, ngModel) {
ngModel.$parsers.unshift(function(v) {
ngModel.$empty = isEmpty();
return v;
});
// needed for first time
var unwatch = scope.$watch(function(){
return isEmpty();
}, function(v){
ngModel.$empty = v;
unwatch();
});
function isEmpty(){
return ngModel.$isEmpty(ngModel.$viewValue);
}
}