问题
Angular 1.4.8.
I have this markup for 2-letter US state codes:
<div class="form-group" ng-class="{'has-error': form.licenseState.$invalid }">
<label for="licenseState" class="control-label">License State</label>
<select name="licenseState" id="licenseState" class="form-control" required
ng-model="ctrl.student.License.State"
ng-options="key as key for (key, value) in ctrl.licenseFormats">
</select>
</div>
This properly gives me an error when the model value is loaded as blank.
However, when the model value is loaded as a value not in the list (bad data), it does not error.
The situation baffles me considering the result is misinformation at all levels. User sees a blank value which appears to be valid (despite required
attribute). Model sees a different value from user which appears to be valid even though it's absent from the valid values list.
Am I missing something? Is there a proper (canonical angular) way to make this trigger a form validation error?
Update
Based on the answer from @paul147, I ended up with this reusable directive for validating a model value against a list.
m.directive('validValues', function() {
return {
scope: {
validValues: '='
},
restrict: 'A',
require: 'ngModel',
link: function (scope, element, attributes, ngModel) {
var values = angular.isArray(scope.validValues)
? scope.validValues
: Object.keys(scope.validValues);
ngModel.$validators.validValues = function (modelValue) {
return values.indexOf(modelValue) !== -1;
}
}
}
});
Example usage:
<select name="licenseState" required valid-values="ctrl.licenseFormats"
ng-model="ctrl.student.License.State"
ng-options="key as key for (key, value) in ctrl.licenseFormats">
</select>
I briefly explored getting the options directly from the select element, but ngOptions puts the values in a custom format. F.ex string:AL
(which is actually a lookup key) for the value of AL
. Further discussion here. Ultimately, the directive is more reusable with less effort if I just do it as above with the redundant declaration of valid values (ctrl.licenseFormats
in this case).
回答1:
One thing you can do to trigger errors on the ngModel directive is to add a custom validator to the ngModel's $validators.
The ngModel's value is passed through the $validators whenever it changes, and an error is raised if the validator returns false.
An example implementation is to add a custom directive to the model's element, and define the validator inside that directive:
Here's a plunkr with a working example: http://plnkr.co/edit/m6OygVR2GyMOXTTVTuhf?p=preview
// markup
<select name="licenseState" id="licenseState" class="form-control" required
ng-model="student.License.State"
ng-options="key as value for (key, value) in licenseFormats"
check-state
license-formats="licenseFormats">
// in the controller
$scope.licenseFormats = {
'OR': 'Oregon',
'WA': 'Washington',
};
// the directive
app.directive('checkState', function() {
return {
scope: {
licenseFormats: '='
},
restrict: 'A',
require: 'ngModel',
link: function(scope, element, attributes, ngModel) {
// defining the validator here
ngModel.$validators.state = function(modelValue) {
return Object.keys(scope.licenseFormats).indexOf(modelValue) > -1;
}
}
}
});
来源:https://stackoverflow.com/questions/35068507/angularjs-select-doesnt-error-when-model-value-not-in-options