2014-03-03 46 views
3

說我有與所述屬性的模型對象favoriteColorsAngularJS驗證表單陣列長度

{ 
    ... 
    favoriteColors: ['red', 'green', 'blue'] 
    .... 
} 

我他們暴露在用戶與NG-重複

<form name="userForm"> 
    ... 
    <ul> 
     <li ng-repeat="color in user.favoriteColors"> 
      <input type="text" ng-model="color" /> 
      <a href="" ng-click="delete(color)">remove</a> 
     </li> 
    </ul> 
    <a href="" ng-click="add()">Add a new favorite color</a> 
    ... 
</form> 

我想能夠檢查favoriteColors字段的有效性做這樣的事情

<div ng-show="userForm.favoriteColors.$error"> 
    You must have at least one favorite color 
</div> 

它doe似乎沒有可能使用內置的驗證器來做到這一點,並且我不確定在哪個元素上我會放置一個自定義指令以獲得ngModelControllerfavoriteColors

回答

0

若要驗證您所請求的方式,你必須使用一個NG-模型把你的顏色數組的形式使該數組可以被驗證。

下面是一個快速的例子,在一個plunker中,我在ngModelController的$ parsers管道上推一個驗證器,它將檢查colors數組的長度。保持colorRequired指令分開將允許你有不需要顏色的情況。您也可以添加到該指令,因此它將在屬性上使用布爾參數,因此您可以在運行時決定是否需要顏色。

http://plnkr.co/edit/yFuSXxacSW811WfZqaPC

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

app.controller('MainCtrl', function($scope) { 
    $scope.colors = ['red', 'blue', 'green']; 
}); 

app.directive("colorGroup", [function() { 
    "use strict"; 
    return { 
     restrict: 'E', 
     require: 'ngModel', 
     template: '<ng-form name="userForm">\ 
       <ul>\ 
       <li ng-repeat="color in model">\ 
       <input type="text" ng-model="color" />\ 
       <a href="" ng-click="delete($index)">remove</a>\ 
       </li>\ 
       </ul>\ 
       </ng-form>', 
     link: function($scope, element, attrs, ngModelCtrl) 
     { 
      $scope.$watch(function(){ 
       return ngModelCtrl.$modelValue; 
      }, function(){ 
       $scope.model = ngModelCtrl.$viewValue; 
      }); 

      $scope.delete = function(idx) 
      { 
         ngModelCtrl.$viewValue.splice(idx, 1); 
         ngModelCtrl.$setViewValue(ngModelCtrl.$viewValue); 
         $scope.model = ngModelCtrl.$viewValue; 
      } 
     } 
    } 
}]); 

app.directive("colorRequired", function() { 
    "use strict"; 
    return { 
     restrict: 'A', 
     require: 'ngModel', 
     link: function($scope, element, attrs, ngModelCtrl) 
     { 
       ngModelCtrl.$setValidity('colorrequired', (ngModelCtrl.$viewValue.length > 0)); 

       ngModelCtrl.$parsers.push(function(viewValue) { 
        var valid = viewValue.length > 0; 
        ngModelCtrl.$setValidity('colorrequired', valid); 
        return valid ? viewValue : undefined; 
       }); 
      } 
     } 
    }); 
+0

啊我看你做了什麼,還有,謝謝! – grivescorbett

+0

*來自[user3677208]的評論(http://stackoverflow.com/users/3677208/user3677208):*有一個問題。如果您將顏色編輯爲其他顏色(不是顏色),您的驗證將無法正常工作。如果輸入編輯器更改了模型,它將不會觸發。你有什麼想法如何解決? –

0

一個清潔的解決方案是隱藏刪除按鈕時,有0或1的顏色,用

<a href="" ng-show="user.favoriteColors.length > 0" ng-click="delete(color)">remove</a> 

或也許禁用它代替使用ng-disabled隱藏它的。

爲了更具體地回答你的問題,更換您的div

<div ng-show="user.favoriteColors.length == 0"> 
    You must have at least one favorite color 
</div> 
14

我的解決辦法是添加一個隱藏的輸入標籤和

<form name="userForm"> 
     ... 
     <ul> 
     <li ng-repeat="color in user.favoriteColors"> 
      <input type="text" ng-model="color" /> 
      <a href="" ng-click="delete(color)">remove</a> 
     </li> 
     </ul> 
     <a href="" ng-click="add()">Add a new favorite color</a> 
     ... 

     <!-- new line --> 
     <input style="display:none" name="colorsLength" type="number" min=1 value="{{user.favoriteColors.length}}"/> 
    </form> 

因此,與數組的長度結合,你可以使用userForm.colorsLength。$錯誤您的驗證。 祝你好運!

+0

請看看我的回答! http://stackoverflow.com/a/32503969/595152你怎麼看? –

9

@Loi Pham,不幸的是我不能評論,所以我不得不添加一個帖子。 我喜歡你的方法。但是我不得不NG-模型添加到輸入,使驗證工作:

<input style="display: none" type="number" name="length" readonly ng-model="colors.length" min="1"> 
+0

請看看我的答案! HTTP://計算器。com/a/32503969/595152你怎麼看? –

5

還有另一種方式加入了指令:

/** 
* Validator for checking an array length. 
* @example 
* <input ng-model="user.favoriteColors" validate-length /> 
*/ 
app.directive('validateLength', function() { 
    return { 
    require: 'ngModel', 
    link: function(scope, element, attrs, ngModel) { 

     // do not set invalid model to undefined, should stay [] 
     ngModel.$options = { 
     allowInvalid: true 
     }; 

     scope.$watch(function() { return ngModel.$modelValue && ngModel.$modelValue.length; }, function() { 
     ngModel.$validate(); // validate again when array changes 
     }); 

     ngModel.$validators.length = function() { 
     var arr = ngModel.$modelValue; 
     if(!arr) { return false; } 

     return arr.length > 0; 
     }; 

    } 
    }; 
}); 
+0

這是迄今爲止最好的解決方案,只是它創建了一個隔離範圍。這在很多用例中都會遇到阻礙。我會改變它來觀看ngModel。$ modelValue.length。 。如:$範圍手錶(函數(){ 回報CTRL $ modelValue.length; },...) – Sam

+0

你是正確的,這將是更好的,當我有時間來檢查這個我會更新我的答案: ) 謝謝! –

+0

@Sam我更新了我的答案:) –