javascript - 带有 scope.$watch 的 Angular 指令强制验证其他字段

标签 javascript angularjs validation angularjs-directive

我编写了一个 match-model Angular 指令,当用户在我的应用程序中注册时,我将其用于密码/密码重复过程。密码重复字段具有此特定属性,可根据原始密码字段验证此字段。

我的指令有 scope.$watch 用于优化目的,因为我不必每次验证我的重复密码范围属性时都读取相关的范围属性值,但我宁愿只使用缓存的值改变当相关范围属性值更改时(原始密码)。

这是我的指令:

.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;
            });
        }
    };
}]);

我的表单包含两个字段(与此问题相关):

<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" />

要求

  1. 当用户输入第一个密码时,如果输入的字符足够多,字段就会生效——在上面的例子中是 6 个字符
  2. 当用户输入第二个密码时,字段应在数据与第一个密码匹配时生效
  3. 如果用户返回到第一个字段并更改原始密码,则第二个字段应该失效

目前如何运作

1 和 2 按预期工作,但 3 没有。这就是为什么我想添加 scope.$digest 以将范围模型更改传播到其他字段。 scope.$watch 是正确的时机,因为它会在特定范围模型属性更改时执行。

似乎 scope.$digest(或 scope.$apply 就此而言)不验证模型。验证似乎没有与它一起执行。

问题

那么我应该如何做类似 scope.$validate 或更好的 element.$validate 这样它只会验证我的特定字段而不是整个模型(结果在 UI 中的形式无效)。

最佳答案

我会通过显式验证 $watch 中的 $viewValue 来实现:

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);
      }
    };
}]);

关于javascript - 带有 scope.$watch 的 Angular 指令强制验证其他字段,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21428615/

相关文章:

javascript - 使用javascript NOT php的电子邮件中的倒数计时器gif

javascript - 如何使用 AngularJS 合并两个对象?

angularjs - 如何与 ng-class 中的字符串进行比较?

python - 在 tkinter 中交互式验证条目小部件内容

c - C中的输入数据验证

php - 当 html 输入名称与列名称不同时使用 Laravel 验证

javascript - JS 全局变量未定义

javascript - 如何在带有闭包的 PrimeFaces 中的命令按钮上定义 oncomplete 事件?

javascript - jQuery 使用 src 选择 img

angularjs - 如何安装 Angular UI Grid 的不稳定版本?