In the following post I will show how to use the built in form functionality in Angular. Through an example I will wire up some common controls and show how to do data binding and validation in the form.
The starting point for using Angular form functionality is defining a form object that serves as a meta object for the elements on the form. For the purposes of this article I have defined an address form with some basic validation requirements.
let group:any = {};
group.firstName = new FormControl('', Validators.required);
group.streetAddress = new FormControl('', Validators.required);
group.zip = new FormControl('', zipValidator);
group.type = new FormControl('home');
this.form = new FormGroup(group);
The above FormGroup defines field names, default values and validation rules. Validators.required is a built in validator, but in order to support custom validation we have defined a custom validator function.
The custom zipValidator function is defined below.
function zipValidator(zip) {
var valid = /^\d{5}$/.test(zip.value);
if(valid){
return null;
}
return {"invalidZip":true};
}
The function returns null if the field is valid, but returns an object with a true value if the validation failed.
Next I will show you how to make use of the form object in the markup template.
<h1>Address Form</h1>
<form (ngSubmit)="onSubmit()" [formGroup]="form" >
<div class="form-row">
<div class="formHeading">First Name</div>
<input type="text" id="firstName" formControlName="firstName">
<div class="errorMessage" *ngIf="form.controls.firstName.touched && !form.controls.firstName.valid">First Name is required</div>
</div>
<div class="form-row">
<div class="formHeading">Street Address</div>
<input type="text" id="streetAddress" formControlName="streetAddress">
<div class="errorMessage" *ngIf="form.controls.streetAddress.touched && !form.controls.streetAddress.valid">Street Address is required</div>
</div>
<div class="form-row">
<div class="formHeading">Zip Code</div>
<input type="text" id="zip" formControlName="zip">
<div class="errorMessage" *ngIf="form.controls.zip.touched && !form.controls.zip.valid">Zip code has to be 5 digits long</div>
</div>
<div class="form-row">
<div class="formHeading">Address Type</div>
<select id="type" formControlName="type">
<option [value]="'home'">Home Address</option>
<option [value]="'billing'">Billing Address</option>
</select>
</div>
<div class="form-row">
<button type="submit" [disabled]="!form.valid">Save</button>
</div>
</form>
The form object is bound to the template, which exposes the individual field rules to the input controls. One example is the zip code field.
form.controls.zip.touched && !form.controls.zip.valid
The code above is used to selectively show the zip code error message if the zip code field is both invalid and interacted with. Another important piece is the formControlName attribute - used to match the input field with the corresponding form control.
The entire code sample is available on Github, but you may also check out a live demo of the form.