2

我決定寫一個自定義指令來幫助驗證我的輸入框。這個想法是,我將我的新花式nx-validate指令添加到引導程序div.form-group,它會檢查我的<input/>$dirty還是$invalid,並根據需要應用.has-success.has-error類。AngularJS自定義表單驗證指令在我的模式下不起作用

由於某種奇怪的原因,我的指令在正常情況下完美工作,但添加的ng-class在ui-bootstrap模式中完全被忽略。

的模式都和形式

<form name="mainForm"> 
    <div class="row"> 
     <div nx-validate class="form-group has-feedback col-lg-6 col-md-6 col-xs-12"> 
      <label class="control-label">Green if long enough, red if not</label> 
      <input type="text" id="name" class="form-control" ng-model="property.name" required="required" ng-minlength="5"/> 
      (once touched I do change colour - happy face) 
     </div> 
    </div>   

和我可愛的指令

nitro.directive("nxValidate", function($compile) { 
    return { 
     restrict: 'A', 
     priority: 2000, 
     compile: function(element) { 

      var node = element; 
      while (node && node[0].tagName != 'FORM') { 
       console.log (node[0].tagName) 
       node = node.parent(); 
      } 
      if (!node) console.error("No form node as parent"); 
      var formName = node.attr("name"); 
      if (!formName) console.error("Form needs a name attribute"); 


      var label = element.find("label"); 
      var input = element.find("input"); 
      var inputId = input.attr("id") 

      if (!label.attr("for")) { 
       label.attr("for", inputId); 
      } 

      if (!input.attr("name")) { 
       input.attr("name", inputId); 
      } 

      if (!input.attr("placeholder")) { 
       input.attr("placeholder", label.html()); 
      } 

      element.attr("ng-class", "{'has-error' : " + formName + "." + inputId + ".$invalid && " + formName + "." + inputId + ".$touched, 'has-success' : " + formName + "." + inputId + ".$valid && " + formName + "." + inputId + ".$touched}"); 
      element.removeAttr("nx-validate"); 

      var fn = $compile(element); 

      return function($scope) { 
       fn($scope); 
      } 

     } 
    } 
}); 

檢查出來的plunker 相同代碼:http://plnkr.co/edit/AjvNi5e6hmXcTgpXgTlH

+0

把你的按鈕在表單內。當我以掠奪者的例子做這件事的時候適用於我。 – juju

回答

3

我建議你最簡單的方法是,你可以通過在這些領域的手錶把那些類,這watcher會說謊的postlink函數內部編譯DOM

return function($scope, element) { 
    fn($scope); 

    $scope.$watch(function(){ 
     return $scope.modalForm.name.$invalid && $scope.modalForm.name.$touched; 
    }, function(newVal){ 
     if(newVal) 
     element.addClass('has-error'); 
     else 
     element.removeClass('has-error'); 
    }) 

    $scope.$watch(function(){ 
     return $scope.modalForm.name.$valid && $scope.modalForm.name.$touched; 
    }, function(newVal){ 
     if(newVal) 
     element.addClass('has-success'); 
     else 
     element.removeClass('has-success'); 
    }) 
} 

Demo Here

後更新

這樣做的實際更好的方法是,而不是從編譯編譯元素,我們需要$compilelink函數本身的元素。使用$compile編譯鏈接fn中的DOM的原因是我們的ng-class屬性包含的範圍變量類似於myForm.name.$invalid,因此當我們$compile編譯函數的DOM時,則它們不計算myForm.name.$invalid變量的值,因爲編譯沒有訪問範圍&總是undefinedblank。因此,在編譯link內的DOM時,所有範圍值都可用,其中包含myForm.name.$invalid,因此,在編譯指令的範圍之後,您將獲得ng-class指令綁定。

代碼

compile: function(element) { 
    //..other code will be as is.. 

    element.removeAttr("nx-validate"); 
     //var fn = $compile(element); //remove this line from compile fn 
     return function($scope, element) { 
     //fn($scope); 
     $compile(element)($scope); //added in postLink to compile dom to get binding working 
     } 
} 

Updated Plunkr

+0

感謝您的回答。你可以向我解釋爲什麼我的例子默認不起作用。除了想要解決這個問題 - 我相信你的答案會是這樣,我想明白爲什麼我首先遇到了問題,並且能夠避免將來發生。是否因爲模態內容是動態的,而且我的指令有錯誤的優先級,或者在錯誤的時間編譯,或者您認爲這是一個範圍界定問題? – Spider

+0

@Spider對於遲到的回覆感到遺憾..請看我更新後的答案。現在應該工作..我認爲這是編譯問題,因爲'ng-class' –

+0

@Spider你看了答案嗎? –