Reactive forms (Angular 5 (2+) Part 1



Introduction


One of the advantages of Angular is a wide range of tools “out of the box”, which allow you to quickly create forms of any complexity.

There are 2 approaches to creating forms in Angular:

Template-driven forms - an approach in which the component template plays a key role, and the entire description is produced in it - this approach is a development of working with forms in AngularJS;

Reactive forms - a new approach for working with reactive style forms. The description of the form occurs in the component in the form of a tree of objects, after which this tree is associated with the template. All manipulations (validation check, subscription to change the value, etc.) are performed in the component, which makes the work more flexible, convenient and predictable.

In this article, we’ll show you how to get started withreactive forms using a simple form with validation and error messages as an example. Code example .

Reactive forms. Part 2.

Create reactive form


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 { }

In reactive forms, 3 types of blocks are used:


All of them are inherited from Abstract Control .

It is convenient to describe the form using the special FormBuilder tool , with which you can create the blocks listed above.

Add to the form component FormBuilder and FormGroup :

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 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 through the directives formGroup and formControlName :






Here you need to pay attention to the fact that formControlName takes the name as a string and is written without [].

We can get the form data in the component as an object via the value property and output them to the template via jsonPipe (at this stage it is necessary to check the health):

{{myFirstReactiveForm.value | json}}

Validation and highlighting of non-valid controls


Angular provides the ability to validate using a list of static methods of the Validators class that verify that the input meets certain conditions.

We use the following:

  • Validators.required - makes the control mandatory;
  • Validators.email - email validation Addresses
  • Validators.pattern - regex validation.

Import the validators from angular / forms into the component:

import { FormGroup, FormBuilder, Validators } from '@angular/forms';

Add them to the description of the form controls:

this.myFirstReactiveForm = this.fb.group({
 name: ['', [
   Validators.required,
   Validators.pattern(/[А-я]/)
  ]
 ],
 email: ['', [
   Validators.required, Validators.email
  ]
 ]
});

Angular dynamically adds paired CSS classes to all form controls, 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 - the control is considered touched at the first loss of focus.

In CSS, add the following styles:

input.ng-touched.ng-invalid{
 border-color: red;
}

Now when you enter incorrect data and lose focus, the controls will have a red border.

Error message output


You can access the control in the component as follows:

this.myFirstReactiveForm.controls[controlName]

Check the invalid and touched properties .

See the full list of properties and control methods here .

Add a method to the component for checking the validity of the control, which takes the control name 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 control div with an error message that will be displayed by * ngIf if the control is not valid:

Имя должно состоять только из русских букв

You can use the ngx-errors library to display various errors (depending on conditions) .

Form submission


Add the onSubmit method to the component :

onSubmit() {
const controls = this.myFirstReactiveForm.controls;
 /** Проверяем форму на валидность */ 
 if (this.myFirstReactiveForm.invalid) {
  /** Если форма не валидна, то помечаем все контролы как touched*/
  Object.keys(controls)
   .forEach(controlName => controls[controlName].markAsTouched());
   /** Прерываем выполнение метода*/
   return;
  }
 /** TODO: Обработка данных формы */
 console.log(this.myFirstReactiveForm.value);
}

If the form is not valid, through foreach 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:


The form is ready!

Conclusion


In the next part we will analyze reactive work with forms, namely:
subscription to the event of change of control;
dynamic reset and blocking of dependent controls;
dynamic addition and removal of controls and groups of controls in the form.

References


See example code here .
More information can be obtained from the official documentation .
Anyone interested in Angular can join the group of the Russian-speaking Angular community in Telegram.

Also popular now: