To implement a custom validator, you need to structure your directive differently by requiring the ngModel
module.
Custom Validator Directive:
return {
require: 'ngModel',
link: function(scope, element, attrs, ngModel) {
// Implement custom max length validation
ngModel.$validators.customMaxLength = function(value) {
var status = false;
if(value.length <= attrs.maxLengthValidator) {
console.log(attrs.maxLengthValidator);
status = true;
}
return status;
};
}
}
It's important to note that if your validation depends on an attribute that can change, you must manually watch the value and run the validator function, as the model update does not trigger the validator automatically.
Add the following to the directive to handle attribute changes:
scope.$watch(function() {
return attrs.maxLengthValidator;
},function() {
ngModel.$validate();
});
If your validator returns false, the form will set $valid
to false
.
HTML Implementation:
In the example below, angular-messages is used to display the validation output. This module is optional but needs to be included.
<form name="myForm">
<div class="form-group" ng-class="{'has-error':myForm.testField.$invalid}">
<label class="control-label" for="testInput">Test Field</label>
<input class="form-control" type="text" name="testField"
max-length-validator="3" required ng-model="testField"/>
</div>
</form>
<div ng-messages ng-messages-multiple class="bg-danger" for="myForm.testField.$error">
<div ng-message when="required">Please enter a value</div>
<div ng-message when="customMaxLength">Value too long</div>
</div>
View Custom Validator Example
About firing the validator on blur:
Avoid updating ngModel if the model value is invalid.
I suggest using styles and a focus attribute with the field to toggle display based on field focus.
Add this to your input field:
ng-focus="myForm.testField.focus=true" ng-blur="myForm.testField.focus=false"
Then use checks with ng-class
, ng-show
, or ng-hide
to update display accordingly.
This enhancement has been included in the Plunker demo.