与范围。$腕表角指令迫使其他领域的验证 [英] Angular directive with scope.$watch to force validation of other fields

查看:158
本文介绍了与范围。$腕表角指令迫使其他领域的验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经写了匹配模型当用户在我的申请注册,我使用的密码/密码,重复的过程角指令。密码重复场有验证这一方面对原来的密码领域这种特殊属性。

我的指令有范围。$看优化的目的,因为我不必每次验证我重复密码scope属性,但我宁愿时间来阅读相关范围属性值只是使用的时候改变范围相关的属性值更改(初始密码)的缓存值

这是我的指令:

  .directive(matchModel,[$超时功能($超时){
    返回{
        要求:ngModel
        链接:功能(范围,元素,属性,ngModelController){            VAR valueCache = NULL;            //看匹配模型模型属性值
            范围。$表(属性[matchModel],功能(为newValue,属性oldValue){
                valueCache =为newValue;
                / *
                。范围$适用(); //错误$进行消化
                $超时(函数(){$范围摘要();}); //没有错误,不工作
                $超时(函数(){$范围适用于();}); //没有错误,不工作
                * /
            });            //添加模型验证解析器
            ngModelController。$ parsers.unshift(函数(值){
                ngModelController $ setValidity(匹配,值=== valueCache)。
                返回值=== valueCache?值:未定义;
            });
        }
    };
}]);

我的表单包含两个字段(即是相关的这个问题)的:

 <输入类型=密码NAME =密码ID =密码占位符=密码
       类=验证自动完成=关闭
       需要
       NG-= MINLENGTH6
       NG-模式=data.password/>
<输入类型=密码NAME =passwordRepeatID =passwordRepeat占位符=重复密码
       类=验证自动完成=关闭
       需要
       NG-模式=data.passwordRepeat
       匹配模型=data.password/>

要求


  1. 当用户输入一个密码,字段时,输入的字符足以成为有效的 - 在这6个字符
  2. 上述情况
  3. 当用户进入第二个密码,字段应该当数据匹配的第一个口令生效

  4. 如果用户返回到第一场和改变原始密码,第二场应该废止

目前它是如何工作的

1和2的工作不如预期,但3没有。这就是为什么我想补充范围。$摘要传播到其他领域范围模式的变化。和范围。$手表是正确的时刻,因为它执行时特定范围内的模型属性的更改。

似乎范围。$摘要(或范围。$适用为此事)不验证模型。验证似乎并没有与它一起执行

问题

所以,我应该怎么做类似范围。$验证甚至更好元素。$验证所以它会只是验证我的特定领域,而不是整个模型(导致无效的形式在UI)。


解决方案

我要通过明确验证$ viewValue里面做了 $观看

<大骨节病> PLUNKER

app.directive(matchModel,[
  功能(){
    返回{
      要求:ngModel
      链接:功能(范围,元素,属性,ngModelController){        VAR valueCache = NULL;        范围。$表(属性[matchModel],功能(为newValue,属性oldValue){
          valueCache =为newValue;
          验证(ngModelController $ viewValue);
        });        VAR验证=功能(值){
          ngModelController $ setValidity(匹配,值=== valueCache)。
          返回值=== valueCache?值:未定义;
        };        ngModelController $ parsers.unshift(验证)。
      }
    };
}]);

I've written a match-model Angular directive that I use for password/password-repeat process when users register in my application. Password repeat field has this particular attribute that validates this field against original password field.

My directive has scope.$watch for optimization purposes because I don't have to read related scope property value each time I validate my repeat password scope property but I rather just use cached value which changes when related scope property value changes (original password).

This is my directive:

.directive("matchModel", ["$timeout", function ($timeout) {
    return {
        require: "ngModel",
        link: function (scope, element, attributes, ngModelController) {

            var valueCache = null;

            // watch "match-model" model property value
            scope.$watch(attributes["matchModel"], function (newValue, oldValue) {
                valueCache = newValue;
                /*
                scope.$apply(); // error $digest in progress
                $timeout(function () { scope.$digest(); }); // no error, not working
                $timeout(function () { scope.$apply(); }); // no error, not working
                */
            });

            // add model validation parser
            ngModelController.$parsers.unshift(function (value) {
                ngModelController.$setValidity("match", value === valueCache);
                return value === valueCache ? value : undefined;
            });
        }
    };
}]);

My form consists of two fields (that are relevant for this question):

<input type="password" name="password" id="password" placeholder="password"
       class="validate" autocomplete="off"
       required
       ng-minlength="6"
       ng-model="data.password" />
<input type="password" name="passwordRepeat" id="passwordRepeat" placeholder="repeat password"
       class="validate" autocomplete="off"
       required
       ng-model="data.passwordRepeat"
       match-model="data.password" />

Requirements

  1. When user enters first password, field becomes valid when enough characters are entered - in above case that's 6 characters
  2. when user enters second password, field should become valid when data matches first password
  3. if user returns to first field and changes original password, second field should invalidate

How it currently works

1 and 2 work as expected, but 3 doesn't. That's why I wanted to add scope.$digest to propagate scope model changes to other fields. And scope.$watch is the right moment because it executes when that particular scope model property changes.

It seems that scope.$digest (or scope.$apply for that matter) doesn't validate model. Validation doesn't seem to be executed along with it.

Question

So how should I do something like scope.$validate or even better element.$validate so it would only validate my particular field instead of the whole model (resulting in invalid form in the UI).

解决方案

I would do it by explicitly validating the $viewValue inside the $watch:

PLUNKER

app.directive("matchModel", [
  function () {
    return {
      require: "ngModel",
      link: function (scope, element, attributes, ngModelController) {

        var valueCache = null;

        scope.$watch(attributes["matchModel"], function (newValue, oldValue) {
          valueCache = newValue;
          validate(ngModelController.$viewValue);
        });

        var validate = function (value) {
          ngModelController.$setValidity("match", value === valueCache);
          return value === valueCache ? value : undefined;
        };

        ngModelController.$parsers.unshift(validate);
      }
    };
}]);

这篇关于与范围。$腕表角指令迫使其他领域的验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆