使用Bootstrap和AngularJS进行表单验证

时间:2016-04-07 18:16:59

标签: javascript angularjs twitter-bootstrap

我正在尝试将AngularJS验证模型与Bootstrap表单验证显示结合起来。

  • 如果用户加载空表单,我不希望表单立即显示错误消息。我想等到用户与表单交互。
  • 如果用户提交的表单中未填写必填字段,我还要显示错误消息。
  • 如果用户开始在字段中输入内容,我希望立即显示错误消息。

所以我必须检查myForm.$submittedmyForm.<fieldName>.$dirty以及myForm.<fieldName>.$touched

然而,它产生了很多重复的代码,只有很少的变化。

我试图制定一个指令来解决这个问题,但我似乎无法找到正确的方法来消除这种复杂性。

HTML:

<div class="form-group required" ng-class="{ 'has-error': myForm.firstname.$invalid && (myForm.firstname.$dirty || myForm.$submitted || myForm.firstname.$touched)  }">
    <label for="firstname" class="control-label" translate>Profile.FirstName</label>
    <input type="text" class="form-control" id="firstname" name="firstname" required ng-model="vm.profile.firstName"/>
    <p class="help-block" ng-if="myForm.firstname.$error.required" translate>Forms.Default.Required</p>
</div>

我想取整个ng-class属性,并用更简洁的东西替换它。该指令似乎是要走的路,所以尝试了这个:

(function(){
    'use strict';
    angular.module('app')
    .directive('hasError', [function(){
        return {
            restrict: 'A',
            scope: {
                form: '=bsForm',
                control: '=bsControl'
            },
            link: function(scope, element){
                scope.$watch('form', function(){
                    var isInvalid = scope.control.$invalid && scope.control.$dirty;
                    element.toggleClass('has-error', isInvalid);
                });

            }
        };
    }]);
})();

用法:

<div class="form-group required" has-error bs-form="myForm" bs-control="myForm.firstname">
...
</div>

form的属性发生变化时,这不会刷新。

我错过了什么?

1 个答案:

答案 0 :(得分:0)

我做了类似这样的事情。我的解决方案略有不同,但在这里可能会有所帮助(您可以在Github上查看要点)。

基本上,我所做的是将所有表单数据包装在单个对象中,然后将该对象分配给<form>属性。然后我观察该对象,只要它发生变化,我就选择ng-dirtyng-invalid类的所有元素(这个选择器可以改成你喜欢的任何东西)。然后我遍历每个元素并为每个元素更新消息。

以下是代码:

(function() {
  "use strict"
  angular.module('app')
    .directive('formValidator', function() {
      return {
        require: '^form',
        scope: {
          formData: '=',
          validateAll: '='
        },
        link: function(scope, element, attrs, ctrls) {
          window.frm = ctrls;
          var selector = '.ng-dirty.ng-invalid';

          function validate() {
            $(".formValidator-input-validation-error-message").remove();
            element.find(selector).each(function(index, el) {
              $el = $(el);
              var messages = [];
              var classes = $el.attr('class').match(/[\d\w-_]+/g);
              for (var i in classes) {
                var lastIndex = classes[i].lastIndexOf('-invalid-');
                if (lastIndex != -1) {
                  var validationMessageAttr = "data-" + classes[i].substr(lastIndex + 9) + "-validation-message";
                  var msg = $el.attr(validationMessageAttr);
                  if (!msg) {
                    msg = element.attr(validationMessageAttr);
                    if (!msg) {
                      msg = "Invalid!";
                    }
                  }
                  messages.push("<div class='validator'>" + msg + "</div>");
                }
              }
              $(el).after("<div style='position:absolute;' class='formValidator-input-validation-error-message'>" + messages.join() + "</div>");
            });
          }
          scope.$watch(function() {
            return scope.formData;
          }, function() {
            validate();
          }, true);
          scope.$watch('validateAll', function(newValue, oldValue) {
            selector = !!newValue ? '.ng-invalid' : '.ng-dirty.ng-invalid';
            validate();
          });
        }
      };
    })
})();