2016-04-07 29 views
0

我試圖將Bootstrap表單驗證顯示與AngularJS驗證模型聯合起來。使用Bootstrap和AngularJS進行表單驗證

  • 如果用戶加載一個空表單,我不希望表單立即顯示錯誤信息。我想等到用戶與表單交互。
  • 如果用戶提交的表單中未填寫必填字段,我還想顯示一條錯誤消息。
  • 如果用戶開始在該字段中輸入內容,我想要立即顯示錯誤消息。

所以我必須檢查myForm.$submitted,myForm.<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性質改變但並沒有讓人耳目一新。

我缺少什麼?

回答

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(); 
      }); 
     } 
     }; 
    }) 
})(); 
1

所以......我設法讓一個指令正常工作了整整我的使用。

如果還有更好的方法,請證明我錯了。

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

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