【问题标题】:AngularJS directive watch validityAngularJS 指令监视有效性
【发布时间】:2013-04-09 10:22:17
【问题描述】:

我尝试创建一个指令,当输入字段被标记为无效时应该执行一些操作。对于这个例子,假设我有一个指令来检查输入是否是素数,并且我想创建一个指令,当它无效时向元素添加一个类:

<input type="text" ng-model="primeNumber" validate-prime invalid-add-class="error">

validate-prime 使用 ng-model 上的解析器和格式化程序来更新模型的有效性。

现在我希望 invalid-add-class 指令在模型无效时添加类“错误”,并在模型有效时将其删除。换句话说,它应该监视模型控制器的 $valid(或 $invalid)属性。但是,我不知道如何使它工作。我试过了:

link : function(scope, element, attrs, ctrl) {
    ctrl.$watch("$valid", function(newVal, oldVal) {
    //never fired
    });
}

也许我可以在范围内观察一些变量,但我不知道要观察哪个变量。

那么当模型的有效性发生变化时如何通知我呢?

【问题讨论】:

  • 如果你能分享你的指令就好了!
  • 我不记得我到底用它做什么了,但 CaioToOn 的第二个解决方案几乎已经是整个链接功能了。当有效性改变时,只有第二个函数的主体应该填充你想要的任何操作。

标签: angularjs


【解决方案1】:

如果您有&lt;form&gt;,请在其中添加name(假设为“myForm”)和name(假设为myInput)。你应该可以$watch这个:

scope.$watch('myForm.myInput.$valid', function(validity) {})

如果您没有form,您可以随时观看功能。这样:

scope.$watch(function() { return ctrl.$valid; }, function(validity){});

您可以阅读有关表单方法here的更多信息。

【讨论】:

    【解决方案2】:

    如果您没有&lt;form /&gt;,您可以轻松获得:

    在你的指令定义中:

    require: '^form'
    

    然后在你的链接函数中,表单作为第四个参数传递:

        link: function (scope, element, attr, ctrl) {
    

    现在您不必对表单或输入字段进行硬编码来执行 $watch:

     scope.$watch(ctrl.$name + '.' + element.attr('name') + '.$valid', 
     function (validity) {}); 
    

    【讨论】:

    • 这太完美了。虽然由于某种原因我不得不使用ctrl[0].$name - 不知道为什么我的控件返回一个 1 形式的数组...
    • 如果'require'属性被传递一个数组,它将返回一个数组(我怀疑它是给你的)
    【解决方案3】:

    总的来说,我们的目标应该是让指令独立于任何一种形式或输入而工作。我们如何允许它读取本地的$valid 属性而不强制将其绑定到单个特定的表单和输入名称?

    只需使用require: 'ngModel' 作为指令配置的属性之一。这会将本地 ngModel 控制器作为链接函数的第四个参数注入,您可以将 $watch 直接放在 $valid 上,而无需将指令的实现耦合到任何特定的表单或输入。

    require: 'ngModel',
    link: function postLink(scope, element, attrs, controller) {
        scope.inputCtrl = controller;
        scope.$watch('inputCtrl.$valid', handlerFunc)
    }
    

    处理程序应该一致地触发具有该结构的 $valid 更改。请参阅 this Fiddle,其中验证输入是否符合美国邮政编码或 Zip+4 的模式。每次有效性更改时,您都会收到提醒。

    编辑 3/21/14:这篇文章之前被我的一个错觉挂断了,专注于实现问题的错误原因。我的错。上面的例子消除了这种固定。此外,还添加了小提琴,表明这种方法确实有效,并且总是有效,一旦您在手表表达式周围添加引号。

    【讨论】:

    • 你确定这行得通吗?因为在我看来,inputCtrl.$valid 似乎会被评估一次(当链接函数被执行时)并且结果被传递给scope.$watch。所以这意味着实际调用将是scope.$watch(true, handlerFunc)scope.$watch(false, handlerFunc),这两者都不会导致变量被监视。
    • inputCtrl.$valid 是对对象属性的引用,而不是原始值。每次$watch 触发时都会对其进行评估。我已经将它用于个人项目,但目前没有可用的良好公开演示。
    • AFAIK inputCtrl.$valid 是一个原语。它要么是true,要么是false,要么是undefined,它们都是原语。您不能创建对对象属性的引用,只能创建对 Javascript 中的对象本身的引用。另请参阅此 JSFiddle:jsfiddle.net/9Mh92/2。如您所见,您的代码不会触发回调,只有引号才会触发。这又是因为您无法创建对任何原语的引用。通过在 inputCtrl.$valid 周围加上引号,您可以指示 Angular 在当前范围内评估该表达式,因此它可以工作。
    • 至于你的require: 'ngModel' 故事,我认为我并没有完全关注你。 AFAIK require 不会改变范围,而是将所需指令的控制器作为链接函数的第四个参数传递。您的范围仍然没有 $valid 属性。所以问题不在于您正在观看原始值,问题在于该值根本不存在。
    • @Tiddo,您对 require 属性的工作方式是绝对正确的。那是我的一个彻头彻尾的放屁,可能是因为筋疲力尽。也就是说,只需在该示例中的 watch 表达式周围添加引号就可以修复它。我已经进行了更新,包括一个 Fiddle 显示它的实际操作。如果有任何问题,请告诉我。
    猜你喜欢
    • 2015-06-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    • 2018-02-11
    • 1970-01-01
    • 2015-05-31
    • 2016-08-11
    • 1970-01-01
    相关资源
    最近更新 更多