AngularJs 原生的 select option 的 required 驗證,
只能對 ng-model 的值為 undefined , "", null , NaN來做 required error。
參考:
ngModel.NgModelController 的 $isEmpty
但如果 ng-model 不是 undefined , "", null , NaN ,且其值不在 select option 中,
此時希望能檢查出驗證錯誤的話 (validation) ,
就需要自己實作。
例如可能的情境為:
如果 option list 裡都是不為 0 的數字,當 ng-model 是數字 0 時 (可能是程式常態 assign 賦值的),此時 required (或 ng-required) 就無法驗證出 required 的 validation error。
以下為我寫出來的簡單實作,
建立了一個名為 selectOptionCheckValidator 的 directive 來進行驗證:
html :
<div ng-app="app" ng-controller="controller as ctrl"> <form name="form"> <label><input type="radio" name="optionType" ng-value="1" ng-model="ctrl.optionType" /> Set option list 1</label> <label><input type="radio" name="optionType" ng-value="2" ng-model="ctrl.optionType" /> Set option list 2</label> <select name="mySelector" ng-model="ctrl.selectedVal" ng-options="selectOption.optionValue.id as selectOption.title for selectOption in ctrl.selectOptionList" select-option-check-validator ng-required="true"> </select> <button ng-click="ctrl.selectedVal = 0"> Set selectedVal to 0 </button> <div> ctrl.selectedVal : {{ctrl.selectedVal}} </div> <div> form.mySelector.$error.selectedValueInOptionList : {{form.mySelector.$error.selectedValueInOptionList ? "invalid" : "valid"}} </div> <div> form.mySelector.$error.selectedValueInOptionList : {{form.mySelector.$error.required ? "invalid" : "valid"}} </div> </form> </div>
angular.module("app", []) .controller("controller", ["$scope", function($scope) { var self = this; self.optionType = 1; self.selectedVal = 0; self.optionList1 = [{ optionValue: { id: 11 }, title: "id 11" }, { optionValue: { id: 12 }, title: "id 12" }]; self.optionList2 = [{ optionValue: { id: 21 }, title: "id 21" }, { optionValue: { id: 22 }, title: "id 22" }]; self.selectOptionList = []; $scope.$watch(angular.bind(this, function() { return this.optionType; }), function(newVal, oldVal) { //if value of selectedValue can not be found in self.selectOptionList, // selectedValue will be assigned to null. if (newVal == 1) { self.selectOptionList = self.optionList1; } else if (newVal == 2) { self.selectOptionList = self.optionList2; self.selectedVal = 21; } }); }]).directive('selectOptionCheckValidator', ["$parse", function($parse) { return { require: 'ngModel', link: function(scope, element, attrs, ngModel) { var regex = /(.+)\sas\s(.+)\sfor\s(.+)\sin\s(.+)/; var matchString = regex.exec(attrs.ngOptions); var collectionExpression = matchString[4]; // "ctrl.selectOptionList" var arryItemVarableName = matchString[3]; // "selectOption" var valueExpression = matchString[1]; // "selectOption.optionValue.id" scope.$watch(collectionExpression, function(newValue, oldValue) { checkIsSelectedValueInOptionList(); }); element.on("change", function() { scope.$apply(function() { checkIsSelectedValueInOptionList(); }); }); function checkIsSelectedValueInOptionList() { var isSelectedValueInOptionList = false; var selectedValue = $parse(attrs.ngModel)(scope); var optionList = $parse(collectionExpression)(scope); if (optionList) { isSelectedValueInOptionList = optionList.some(function(option) { // create a custom scope object to render optionValue from valueExpression var optionTempObject = new function(){ this[arryItemVarableName] = option; }; var optionValue = $parse(valueExpression)(optionTempObject); return optionValue == selectedValue; }); ngModel.$setValidity("selectedValueInOptionList", isSelectedValueInOptionList); } } } }; }]);
在這個例子裡,設置了兩個 option list 作為 <select> 的 option 選項,
Note
此例中用來解析 ng-option 字串的正規表達式較為簡易,
如果想知道完整的正規表達式,也就是可以解析 AngularJs ng-option 所有可能字串的正規達式,
可以參考官方源碼,其中可以看到正規表達式為:
^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([$\w][$\w]*)|(?:\(\s*([$\w][$\w]*)\s*,\s*([$\w][$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$
圖例:
沒有留言 :
張貼留言