Following the example here :
https://angular.io/docs/ts/latest/guide/forms.html
My form looks like:
<input type="text" class="form-control" id="name"
required
[(ngModel)]="model.name" name="name"
#name="ngModel" >
<div [hidden]="name.valid || name.pristine"
class="alert alert-danger">
I want to add some custom validation to this form. I did find some advise about using ngFormModel and FormBuilders and Validation class, however I believe these are outdated and no longer recommended
( http://almerosteyn.com/2016/03/angular2-form-validation-component)
My question then is how do I add custom validation.
In angular 1.x I used to add functions to ngModel.$parsers and ngModel.$formatters pipeline. What is the equivalent in angular 2 ?
I do it by using a model-driven approach, instead of template-driven. For example:
Form
<form [formGroup]="myForm">
<label for="id-name">Name</label>
<input type="text" id="id-name" formControlName="name">
<label for="id-age">Age</label>
<input type="text" id="id-age" formControlName="age">
</form>
Component
export class MyComponent implements OnInit {
myForm:FormGroup;
ngOnInit() {
let fuv = FormUtils.validators;
this.myForm = this.formBuilder.group({
name: ['', Validators.required],
age: ['', [Validators.required, fuv.isNumber]],
});
}
}
FormUtils
type ValidatorResult = {[key:string]:any};
function _isNumber(control:AbstractControl):ValidatorResult {
let v = control.value;
if (isPresent(v) && !isNumber(v) && !isEmptyString(v)) {
return {'isNumber': false};
}
return null;
}
export class FormUtils {
static validators = {
isNumber: _isNumber
}
}
Here, isPresent
, isNumber
, and isEmptyString
are pretty straightforward:
isPresent(obj) --> return obj !== undefined && obj !== null;
isNumber(obj) --> return (typeof obj === 'number' && !isNaN(obj));
isEmptyString(obj) --> return obj === '';
Currently, Angular 2 gives you four useful validators: required
, minLength
, maxLength
, and pattern
. The last one is pretty powerful. You can write your own validators following a pattern similar to _isNumber
above. If your validator requires a parameter (e.g. lessThan
), then you can use a pattern similar to this:
function lessThan(maxVal:number):ValidatorFn {
return (control:AbstractControl):ValidatorResult => {
let value = control.value;
if (isPresent(value) && !isEmptyString(value) && isNumber(value) && parseInt(value) >= maxValue) {
return {'lessThan': {'maxValue': maxValue, 'actual': value}};
}
return null;
};
}
I understand that this approach (model-driven) is different from the form that you posted in your question (template-driven). I hope it helps anyway.
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