Angularjs 自定义ngModel标志不';我不能马上消化

Angularjs 自定义ngModel标志不';我不能马上消化,angularjs,Angularjs,我正在尝试扩展ngModel,这样我就有了$empty标志,即使验证失败也能正常工作。我们用它来显示一个“明文”按钮 模型覆盖工作正常,但我注意到标记更改不会立即应用。调用$digest会引发“进行中”错误 您是否被迫使用keyup事件?为了避免摘要计时的问题,您应该使用连接到ngModel的管道 Fiddle:我发现,$timeout可以工作,它可以在下一个周期设置我的代码: element.on('keyup', function() { $timeout(checkEmpty);

我正在尝试扩展
ngModel
,这样我就有了
$empty
标志,即使验证失败也能正常工作。我们用它来显示一个“明文”按钮

模型覆盖工作正常,但我注意到标记更改不会立即应用。调用
$digest
会引发“进行中”错误


您是否被迫使用keyup事件?为了避免摘要计时的问题,您应该使用连接到ngModel的管道


Fiddle:

我发现,
$timeout
可以工作,它可以在下一个周期设置我的代码:

element.on('keyup', function() {
     $timeout(checkEmpty);
});

您只需
$watch
进行更改并设置变量即可:

scope.$watch(function(){
   return ngModel.$isEmpty(ngModel.$viewValue);
},
function(v){
   ngModel.$empty = v;
})
编辑:

当然,这是低效的,因为它注册了
$watch

正如注释中正确指出的那样,
$viewchangelisters
不会为无效条目触发。绑定到元素事件也是不好的,因为
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);
  }
}

哪个标志不会立即应用?ngModel.$empty。任何监视此值的内容在下一个周期之前都无法更新。我不希望使用keyup,但当我输入无效字符时,viewchangelisteners不会启动。这对鼠标事件(例如,右键单击+剪切)不起作用实际上,这是一个坏主意,因为它将本来与DOM无关的
ngModel
绑定到底层DOM元素。我更新了我的答案,因为我原来的方法效率很低,因为增加了$watch,这很有效,让我走上了正确的道路。我有一个与此无关的常见问题,我的ngModel指令从未“链接”。它在JSFIDLE中工作得很好,有什么快速的想法会导致这种情况吗?
scope.$watch(function(){
   return ngModel.$isEmpty(ngModel.$viewValue);
},
function(v){
   ngModel.$empty = v;
})
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);
  }
}