
Introduction
One of the advantages of Angular is a wide range of out-of-the-box tools that allow you to quickly create shapes of any complexity.
In Angular, there are 2 approaches to creating forms:
')
Template-driven forms - an approach in which the component template plays a key role, and the entire description is made in it - this approach is the development of working with forms in AngularJS;
Reactive forms - a new approach for working with forms in a reactive style. The form description occurs in the component in the form of a tree of objects, after which this tree is associated with the template. All manipulations (validity check, subscription to change values, etc.) are performed in the component, which makes the work more flexible, convenient and predictable.
In this article we will discuss how to start working with
reactive forms on the example of a simple form with validation and error messages.
Sample codeReactive forms. Part 2.Creating a reactive form
Let's connect the
ReactiveFormsModule to the module in which we will use the form:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { ReactiveFormsModule } from '@angular/forms'; import { AppComponent } from './app.component'; @NgModule({ imports: [ BrowserModule, ReactiveFormsModule ], declarations: [ AppComponent ], bootstrap: [ AppComponent ] }) export class AppModule { }
Reactive forms use 3 types of blocks:
All of them are inherited from
Abstract Control .
It is convenient to describe a form using the special
FormBuilder tool, with which you can create the blocks listed above.
Add the
FormBuilder and
FormGroup to the component:
import { Component } from '@angular/core'; import { FormGroup, FormBuilder } from '@angular/forms'; @Component({ selector: 'my-app', templateUrl: './app.component.html', styleUrls: [ './app.component.css' ] }) export class AppComponent implements OnInit { myFirstReactiveForm: FormGroup; constructor(private fb: FormBuilder){} ngOnInit(){} }
Now we will describe the form and
initialize it in ngOnInit:
export class AppComponent implements OnInit { myFirstReactiveForm: FormGroup; constructor(private fb: FormBuilder){} ngOnInit(){ this.initForm(); } initForm(){ this.myFirstReactiveForm = this.fb.group({ name: [''], email: [null] }); } }
This form consists of two controls:
- name with the value "Ivan" during initialization;
- emai l without starting value.
Associate the form with the component template via the
formGroup and
formControlName directives :
<form [formGroup]="myFirstReactiveForm"> <label for="name"></label> <input type="text" id="name" formControlName="name" /> <br/><br/> <label for="email">email</label> <input type="text" id="email" formControlName="email" /> <br/><br/> <button type="submit"></button> </form>
Here you need to pay attention to the fact that formControlName takes a name as a string and is written without [].We can get the form data in the component as an object through the
value property and output them to a template via
jsonPipe (at this stage it is necessary for the functional check):
<div> {{myFirstReactiveForm.value | json}} </div>
Validation and illumination of non valid controls
Angular provides the ability to validate using a list of static methods of the
Validators class that check for the compliance with certain conditions.
We use the following:
- Validators.required - makes control mandatory;
- Validators.email - email validation addresses;
- Validators.pattern - regular expression validation.
Import validators from
angular / forms into the component:
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
Add them to the form controls description:
this.myFirstReactiveForm = this.fb.group({ name: ['', [ Validators.required, Validators.pattern(/[-]/) ] ], email: ['', [ Validators.required, Validators.email ] ] });
Angular dynamically adds CSS classes to all controls of the form, depending on certain conditions:
- ng-invalid / ng-valid - changes depending on the validity of the control;
- ng-pristine / ng-dirty - the control is considered dirty if the value has changed at least once;
- ng-untouched / ng-touched - control is considered to be touched at the first loss of focus.
Add the following styles to CSS:
input.ng-touched.ng-invalid{ border-color: red; }
Now when entering invalid data and losing focus, the controls will have a red border.Error message
You can access the control in the component as follows:
this.myFirstReactiveForm.controls[controlName]
Check the
invalid and
touched properties.
The full list of properties and methods of control is
here .
Add a method to the component to check the validity of the control, which accepts the name of the control as input and returns true / false:
isControlInvalid(controlName: string): boolean { const control = this.myFirstReactiveForm.controls[controlName]; const result = control.invalid && control.touched; return result; }
In the template, add a div under the control with an error message that will be displayed by * ngIf, if the control is not valid:
<label for="name"></label> <input type="text" id="name" formControlName="name" /> <div class="error" *ngIf="isControlInvalid('name')"> </div>
To display different errors (depending on conditions), you can use the ngx-errors library.Form submission
Add the
onSubmit method to the component:
onSubmit() { const controls = this.myFirstReactiveForm.controls; if (this.myFirstReactiveForm.invalid) { Object.keys(controls) .forEach(controlName => controls[controlName].markAsTouched()); return; } console.log(this.myFirstReactiveForm.value); }
If the form is not valid, through foreach we mark all controls as touched to highlight errors and interrupt the execution of the method. Otherwise, we process the form data.Add a
submit event handler to the template:
<form [formGroup]="myFirstReactiveForm" (submit)="onSubmit()">
The form is ready!
Conclusion
In the next part we will analyze the reactive work with the forms, namely:
subscription to the change control event;
dynamic reset and blocking of dependent controls;
Dynamic addition and removal of controls and control groups to a form.
Links
See example code
here .
More information can be obtained from the
official documentation .
Anyone interested in Angular can join the
Russian-speaking Angular community group in Telegram.