【问题标题】:AngularJS form validation directive for showing input errors用于显示输入错误的 AngularJS 表单验证指令
【发布时间】:2014-08-13 04:46:32
【问题描述】:

我需要创建一个验证指令来自动显示每个输入的所有输入错误。 此验证指令应显示当前的所有错误,并且应在用户键入时自动更新错误列表。

如果输入是脏的、非空的和无效的,我需要显示输入的所有错误。我需要将所有错误添加到此输入元素附近的 html 元素中。

例如,如果输入有 type="email" 和 ng-minlength="5" 并且用户输入了 'abc',我需要在此输入附近显示此类错误:'Invalid email;请输入至少 5 个字符;'

例如,如果输入的 type="number" attr 和 min="200" 和 min-model="minnumber" 和 minnumber 模型设置为 '300' 并且用户输入了 '100' 我需要在此附近显示此类错误input: '请输入最小数量500;应该大于 Min Number;'

如果相关模型(最小模型参数)更新,我还需要更新上一个示例中输入的所有错误消息。

var app = angular.module('app', []);

app.controller('appCtrl', function ($scope) {

});

app.directive('validate', function () {
    return {
        restrict: 'A',
        require: 'ngModel', // require:  '^form',

        link: function (scope, element, attrs, ctrl) {
            console.log('======================');
            console.log(scope);
            console.log(element);
            console.log(attrs);
            console.log(ctrl);
            console.log(scope.form.$error);
            angular.forEach(scope.form.$error, function (value, key) {
                console.log('scope.form.$error = ' + key + ': ' + value);
                console.log(value);
            });

        }
    };
});


app.directive('positiveInteger', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                var INTEGER_REGEXP = /^\d+$/;
                if (INTEGER_REGEXP.test(viewValue)) { // it is valid
                    ctrl.$setValidity('positiveInteger', true);
                    return viewValue;
                } else { // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('positiveInteger', false);
                    return undefined;
                }
            });
        }
    };
});


app.directive('positiveFloat', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                var FLOAT_REGEXP = /^(?:[1-9]\d*|0)?(?:\.\d+)?$/;
                if (FLOAT_REGEXP.test(viewValue)) { // it is valid
                    ctrl.$setValidity('positiveInteger', true);
                    return viewValue;
                } else { // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('positiveInteger', false);
                    return undefined;
                }
            });
        }
    };
});


app.directive('minModel', function () {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, element, attrs, ctrl) {
            ctrl.$parsers.unshift(function (viewValue) {
                if (viewValue > scope[attrs.minModel]) { // it is valid
                    ctrl.$setValidity('minModel', true);
                    return viewValue;
                } else { // it is invalid, return undefined (no model update)
                    ctrl.$setValidity('minModel', false);
                    return undefined;
                }
            });

        }
    };
});

您能帮忙制定这个验证指令吗?

或者你能指出我正确的方向吗?

Link to JSFiddle with some code for testing.

附: UI-Utils 也有类似的东西,但他们的指令不能在一个地方设置类似的错误消息。

【问题讨论】:

标签: javascript angularjs validation angularjs-directive


【解决方案1】:

我想建议看看这篇文章,这篇文章作者正在解释如何实现你的目标,你可以深入研究代码。 link

此帖子中显示错误消息的示例

module = angular.module('app', []);

module.directive('showErrors', function($timeout) {
    return {
      restrict: 'A',
      require: '^form',
      link: function (scope, el, attrs, formCtrl) {
        // find the text box element, which has the 'name' attribute
        var inputEl   = el[0].querySelector("[name]");
        // convert the native text box element to an angular element
        var inputNgEl = angular.element(inputEl);
        // get the name on the text box
        var inputName = inputNgEl.attr('name');

        // only apply the has-error class after the user leaves the text box
        var blurred = false;
        inputNgEl.bind('blur', function() {
          blurred = true;
          el.toggleClass('has-error', formCtrl[inputName].$invalid);
        });

        scope.$watch(function() {
          return formCtrl[inputName].$invalid
        }, function(invalid) {
          // we only want to toggle the has-error class after the blur
          // event or if the control becomes valid
          if (!blurred && invalid) { return }
          el.toggleClass('has-error', invalid);
        });

        scope.$on('show-errors-check-validity', function() {
          el.toggleClass('has-error', formCtrl[inputName].$invalid);
        });

        scope.$on('show-errors-reset', function() {
          $timeout(function() {
            el.removeClass('has-error');
          }, 0, false);
        });
      }
    }
  });

module.controller('NewUserController', function($scope) {
  $scope.save = function() {
    $scope.$broadcast('show-errors-check-validity');

    if ($scope.userForm.$valid) {
      alert('User saved');
      $scope.reset();
    }
  };

  $scope.reset = function() {
    $scope.$broadcast('show-errors-reset');
    $scope.user = { name: '', email: '' };
  }
});

【讨论】:

    【解决方案2】:

    看看ng-messagesdirective。它相当优雅。示例:

    <form name="myForm">
      <input type="text" ng-model="field" name="myField" required minlength="5" />
      <div ng-messages="myForm.myField.$error">
        <div ng-message="required">You did not enter a field</div>
        <div ng-message="minlength">The value entered is too short</div>
      </div>
    </form>
    

    然后您可以将它与任何表单验证结合使用。只需将来自验证器的错误消息放到元素 $error 对象上,它们就会自动呈现在您的 UI 中。

    【讨论】:

      【解决方案3】:

      这是我使用的模式(Angular 1.3):

      app.directive('number', function() {
        var NUMBER_REGEXP = /^(\d+)$/;
        return {
          require: 'ngModel',
          link: function(scope, elm, attrs, ctrl) {
            ctrl.$validators.number = function(modelValue, viewValue) {
              return NUMBER_REGEXP.test(viewValue);
            };
          }
        };
      });
      

      然后我能够使用这种模式检查 HTML 中的错误(使用 Bootstrap 3.3):

      <form name="form">
        <div class="form-group"
             ng-class="{'has-error': form.value.$dirty && form.value.$error.number}">
          <label for="id_value" class="control-label">Value:</label>
          <div>
            <input type="text" class="form-control" id="id_value" name="value"
                   ng-model="model.number" number>
            <p class="help-block" ng-if="form.value.$error.number">Please enter a number</p>
          </div>
        </div>
      </form>
      

      解释:

      &lt;input name="value"&gt; 标记中的number 属性触发指令,这会导致调用ngModel 验证器'number' 并设置/取消设置value.$error.number

      如果设置了value.$error.number,则has-error 类将应用于form-group,因此它会显示一个红色的输入字段并显示帮助消息。

      【讨论】:

        【解决方案4】:

        all input errors for each input automatically

        就我个人而言,我认为这句话的弊多于利。

        1。将错误消息从 html 隐藏到 javascript 中。

        • 我认为最好显示尽可能多的信息。尽可能以易于理解的方式向使用 html 的开发人员提供,
          我相信这是要走的路。

        2。为未来的自定义错误消息增加复杂性。

        • 如果您的下一位开发人员想要将错误消息更改为 Hey, your input is too short
          你想让他放弃你的一般错误信息吗?或者,在您的 javascript 中更改它?

        • 如果您的下一位开发人员使用 ng-show 添加自定义错误消息会怎样。
          然后,您将收到两条含义相同的错误消息。
          那么,你会不允许拥有它吗?或者,您的一般指令错误信息应该被隐藏?或者,将该自定义错误消息应用到一般错误消息中?如果是这样,那怎么办?看,它变得复杂了。

        恕我直言,此一般错误消息仅在您非常确定以下内容时才有效;

        • 许多页面上的错误消息都是相同的。
        • 错误消息在任何情况下都不会改变。
        • html 开发人员不应关心错误消息。
        • 不允许自定义错误消息。

        如果您不确定我提到的上述内容,我建议不要创建一般错误消息。

        【讨论】:

          猜你喜欢
          • 2014-02-23
          • 2021-01-08
          • 2014-08-02
          • 2013-05-31
          • 1970-01-01
          • 1970-01-01
          • 2014-10-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多