javascript - 是否可以在没有深度 $watch 的情况下检测指令中对 ng-model 的更改

标签 javascript angularjs

我正在编写一个带有自定义验证逻辑的指令来验证一个对象。

HTML:

<input type="hidden" name="obj" ng-model="vm.obj" validate-object />

JS:

angular
  .module('myApp')
  .directive('validateObject', function () {
    return {
      restrict: 'A',
      require: 'ngModel',
      link: function (scope, element, attrs, ngModelCtrl) {
        ngModelCtrl.$validators.validateObject = myValidator;

        function myValidator (modelValue, viewValue) {
          return validateObject(modelValue);
        }

        function validateObject (obj) {
          // Look inside the object
        }
      }
    }
  });

问题在于,当对象内部的属性发生更改时,验证程序不会运行。

我可以使用 objectEquality === true 添加一个 $watch,然后使用我的验证逻辑手动添加 $setCustomValidity。像这样:

link: function (scope, element, attrs, ngModelCtrl) {
  scope.$watch(attrs.ngModel, onModelChange, true);

  function onModelChange (newValue) {
    ngModelCtrl.$setCustomValidity('validateObject', validateObject(newValue))
  }

  function validateObject (obj) {
    // Look inside the object
  }
}

但我不喜欢使用手动使用 $setValidity 的老派方法,再加上手动添加一个 $watchNgModelController 已经有在更新过程中注册的方法(如 $formatters),此外 $watch 是一个很深的方法,可能会出现性能问题。

我是不是理解错了?有没有更好的办法?

最佳答案

来自 https://github.com/angular/angular.js/blob/master/src/ng/directive/ngModel.js#L699 :

if (ctrl.$$lastCommittedViewValue === viewValue && (viewValue !== '' || !ctrl.$$hasNativeValidators)) {
  return;
}

ngModel 对模型的旧版本执行平面相等性检查,因此对象内部的任何更改都不会反射(reflect)在 ngModel 或 ngChange 上。

首选方法是使用不可变数据,这意味着每次更改模型(对象)时,都创建一个新副本:

function changeModel(){
  this.vm.name = "roy";
  // Create a new object for ngModel;
  this.vm = angular.copy(this.vm);
}

编辑

我记得我之前解决过一个问题。您希望将一组 ng-models 绑定(bind)到对象的属性,并为整个对象设置一个更改监听器。

这是我的解决方案:http://plnkr.co/edit/6tPMrB8n1agINMo252F2?p=preview

我所做的是创建一个必须放置在表单元素上的新指令“formModel”。 Angular 有一个表单指令,它有一个 Controller 。 NgModelController 需要一个父表单 Controller ,然后它将自己添加到表单中(这就是您在整个表单上获得有效性的方式)。 因此,在我的指令中,我装饰了表单的 $addControl 方法,并为每个通过 $viewChangeListeners 添加自身的 ngModelController 添加了一个监听器,现在在表单内每次更改 ngModel 时,formModel 指令将复制整个对象并触发 $setViewValue .

关于javascript - 是否可以在没有深度 $watch 的情况下检测指令中对 ng-model 的更改,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39346380/

相关文章:

javascript - 如何从 Nuxt.js SPA 运行 Python 脚本?

javascript - 如何制作警报动画?

javascript - 如何使用按钮执行 ng-include ?

javascript - 无法从 Controller 中的函数获取数据以进行 ng-repeat

javascript - 时区转换层

javascript - 如何将 Bootstrap 日期选择器与 Meteor 一起使用

javascript - 使用jquery从YouTube提要xml抓取视频ID

javascript - 监听不同元素上的多个触发事件后触发函数

javascript - 解析云代码 : How to Invoke Promises for Async Saving

javascript - 刷新 Angular JS Factory,无需重新加载页面