How to add form validation pattern in Angular 2?
Since version 2.0.0-beta.8 (2016-03-02), Angular now includes a Validators.pattern
regex validator.
See the CHANGELOG
custom validation step by step
Html template
<form [ngFormModel]="demoForm">
<input
name="NotAllowSpecialCharacters"
type="text"
#demo="ngForm"
[ngFormControl] ="demoForm.controls['spec']"
>
<div class='error' *ngIf="demo.control.touched">
<div *ngIf="demo.control.hasError('required')"> field is required.</div>
<div *ngIf="demo.control.hasError('invalidChar')">Special Characters are not Allowed</div>
</div>
</form>
Component App.ts
import {Control, ControlGroup, FormBuilder, Validators, NgForm, NgClass} from 'angular2/common';
import {CustomValidator} from '../../yourServices/validatorService';
under class define
demoForm: ControlGroup;
constructor( @Inject(FormBuilder) private Fb: FormBuilder ) {
this.demoForm = Fb.group({
spec: new Control('', Validators.compose([Validators.required, CustomValidator.specialCharValidator])),
})
}
under {../../yourServices/validatorService.ts}
export class CustomValidator {
static specialCharValidator(control: Control): { [key: string]: any } {
if (control.value) {
if (!control.value.match(/[-!$%^&*()_+|~=`{}\[\]:";#@'<>?,.\/]/)) {
return null;
}
else {
return { 'invalidChar': true };
}
}
}
}
You could build your form using FormBuilder as it let you more flexible way to configure form.
export class MyComp {
form: ControlGroup;
constructor(@Inject()fb: FormBuilder) {
this.form = fb.group({
foo: ['', MyValidators.regex(/^(?!\s|.*\s$).*$/)]
});
}
Then in your template :
<input type="text" ngControl="foo" />
<div *ngIf="!form.foo.valid">Please correct foo entry !</div>
You can also customize ng-invalid CSS class.
As there is actually no validators for regex, you have to write your own. It is a simple function that takes a control in input, and return null if valid or a StringMap if invalid.
export class MyValidators {
static regex(pattern: string): Function {
return (control: Control): {[key: string]: any} => {
return control.value.match(pattern) ? null : {pattern: true};
};
}
}
Hope that it help you.
Now, you don't need to use FormBuilder
and all this complicated valiation angular stuff. I put more details from this (Angular 2.0.8 - 3march2016):
https://github.com/angular/angular/commit/38cb526
Example from repo :
<input [ngControl]="fullName" pattern="[a-zA-Z ]*">
I test it and it works :) - here is my code:
<form (ngSubmit)="onSubmit(room)" #roomForm='ngForm' >
...
<input
id='room-capacity'
type="text"
class="form-control"
[(ngModel)]='room.capacity'
ngControl="capacity"
required
pattern="[0-9]+"
#capacity='ngForm'>
Alternative approach (UPDATE June 2017)
Validation is ONLY on server side. If something is wrong then server return error code e.g HTTP 400 and following json object in response body (as example):
this.err = {
"capacity" : "too_small"
"filed_name" : "error_name",
"field2_name" : "other_error_name",
...
}
In html template I use separate tag (div/span/small etc.)
<input [(ngModel)]='room.capacity' ...>
<small *ngIf="err.capacity" ...>{{ translate(err.capacity) }}</small>
If in 'capacity' is error then tag with msg translation will be visible. This approach have following advantages:
- it is very simple
- avoid backend validation code duplication on frontend (for regexp validation this can either prevent or complicate ReDoS attacks)
- control on way the error is shown (e.g.
<small>
tag) - backend return error_name which is easy to translate to proper language in frontend
Of course sometimes I make exception if validation is needed on frontend side (e.g. retypePassword
field on registration is never send to server).