I have an asynchronous Formly field-validation function that is used in several forms and checks multiple aspects of the field. I'd like to be able to "return" (in a general sense) error text from the field-validation function that spells out exactly what is wrong with the field.
What is the best way to do that? I'd guess that I want to emit the text into the scope, but I'm not sure where. I've dug through all the examples (I think) and don't see anything germane.
I do this through a combination of formlyValidationMessages and a fieldWrapper. The initial configuration is pretty daunting, but results in a pretty flexible validation system that allows you to handle synchronous and asynchronous validation errors the same. Most of this post was cobbled together from the official async Validation example.
formlyValidationMessages allows you to configure some default error messages for typical validation errors. Here's an example I use in my projects
angular.module('myModule', ['formly']).run(formlyValidationMessages){
formlyValidationMessages.messages.required = 'to.label + " is required"'
formlyValidationMessages.messages.max = '"The max value allowed is " + to.max'
formlyValidationMessages.messages.min = '"The min value allowed is " + to.min'
}
These are Formly Expressions so they can be strings or functions.
This basically sets a watch on the fields error property in the angular form. If it there's an error in the form for the field, (e.g. form.field.$error.required === true), it'll add max to validation.messages in your field configuration object.
If you need a specific error for a specific field you can add it to the field definition. e.g.
var field = {
key: 'serialNumber',
type: 'input'
....
validation: {
messages: {
unique: function() {
return 'Serial number 123 is not unique'
}
}
}
asyncValidators: {
unique: {
expression: function(modelValue, viewValue, scope) {
return $timeout(
function(){
if(modelValue === '123') {
throw 'unique failure: 123' //throw to reject promise
}
},
1000
)
}
}
}
}
To display this to the user, create a hasError wrapper for your fields that uses ngMessages to create a per field error list for your fields.
module.config(function(formlyConfigProvider) {
formlyConfigProvider.setWrapper({
name: 'hasError',
template: '<div class="form-group" ng-class="{\'has-error\': showError}">' +
' <label class="control-label" for="{{id}}">{{to.label}}</label>' +
' <formly-transclude></formly-transclude>' +
' <div ng-messages="fc.$error" ng-if="showError" class="text-danger">' +
' <div ng-message="{{ ::name }}" ng-repeat="(name, message) in ::options.validation.messages" class="message">{{ message(fc.$viewValue)}}</div>' +
' </div>' +
'</div>'
})
})
Here is a plunker that has a functioning example using bootstrap styling. If you input 123, you'll get an asynchronous validation error, but if you leave it blank you'll get a synchronous one.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With