Angular 5 Reactive Forms And Validations

As we have seen in the last article, there are two types of form development approach that we use in Angular 5. The first one is template-driven and the other one is the reactive forms approach. Let us explore what are reactive forms and how to validate these in Angular 5.

What are reactive forms?

This approach uses the Reactive forms for developing the forms which favor the explicit management of data between the UI and the Model. With this approach, we create the tree of Angular form controls and bind them in the native form controls. As we can create the form controls directly in the component, it makes it a bit easier to push the data between the data models and the UI elements.

Initial imports for using reactive forms

To begin using the reactive forms, we must ensure that we are importing the proper references in the project and at the right location. Before we start, let’s add the new component using this command in the command prompt.

ng g c [name of component]
 
In this, I have added the component in my code. The name of the component is ReactiveDemoComponent. Okay. After adding the component, the first import we need to do is our bootstrap module or application module (i.e.app. module.ts). The code snippet for that is as shown below.
  1. import { BrowserModule } from '@angular/platform-browser';  
  2. import { NgModule } from '@angular/core';  
  3. import {ReactiveFormsModule} from '@angular/forms'  
  4. import { AppComponent } from './app.component';  
  5. import { ReactiveDemoComponent } from './reactive-demo/reactive-demo.component';  
  6.   
  7. @NgModule({  
  8.   declarations: [  
  9.     AppComponent,  
  10.     ReactiveDemoComponent  
  11.   ],  
  12.   imports: [  
  13.     BrowserModule,  
  14.     ReactiveFormsModule  
  15.   ],  
  16.   providers: [],  
  17.   bootstrap: [AppComponent]  
  18. })  
  19. export class AppModule { }  

In this, what we have done is that we have imported the ReactiveFormsModule and added that module in the imports array. The next change we need to do is in the component, where we simply add these 3 packages in the import section.

  1. import { Component, OnInit } from '@angular/core';  
  2. import {FormGroup,FormControl,FormBuilder} from '@angular/forms'  
  3. @Component({  
  4.   selector: 'app-reactive-demo',  
  5.   templateUrl: './reactive-demo.component.html',  
  6.   styleUrls: ['./reactive-demo.component.css']  
  7. })  
  8. export class ReactiveDemoComponent implements OnInit {  
  9.                    constructor() { }  
  10.                   ngOnInit() {}}  

To sum up, we have 2 basic steps -

  1. Import ReactiveFormsModule in the application module and add it in import array.
  2. import the formgroup,formcontrol and FormBuilder classes to the component.

FormControl

It tracks the value of the controls and validates the individual control in the form.

FormGroup

Tracks the validity and state of the group of FormControl Instance or moreover, we can say the formgroup to be a collection of FormControls.

FormBuilder

This helps us to develop the forms along with their initial value and there validations.

Designing the component code

Now, we know the basics of the formcontrol, formgroup, and formbuilder. Let us design the form in the component snippet. For that, the code can be like below.

  1. import { Component, OnInit } from '@angular/core';  
  2. import {FormBuilder,FormGroup,FormControl,Validators,NgForm} from '@angular/forms'  
  3. @Component({  
  4.   selector: 'app-reactive-demo',  
  5.   templateUrl: './reactive-demo.component.html',  
  6.   styleUrls: ['./reactive-demo.component.css']  
  7. })  
  8. export class ReactiveDemoComponent implements OnInit {  
  9. signupForm:FormGroup;  
  10. FirstName:string="";  
  11. LastName:string="";  
  12. Email:string="";  
  13. Password:string="";  
  14. constructor(private frmbuilder:FormBuilder)  
  15.    {  
  16.     
  17.     this.signupForm=frmbuilder.group({  
  18.     fname:new FormControl(),  
  19.     lname:new FormControl(),  
  20.     Emailid:new FormControl(),  
  21.     userpassword:new FormControl()  
  22.     });  
  23.    }  
  24.   ngOnInit() {  
  25.   }  
  26.   PostData(signupForm:NgForm)  
  27.   {  
  28.     console.log(signupForm.controls);  
  29.   }  
  30.   
  31. }  

In the above code, we have designed our form in the component. As we know, in the reactive forms approach, we design the forms in the template and then do the bindings for the HTML.

What we have done in this code is -

  1. We have declared the FormGroup property and named it signupForm in the component.
  2. In Constructor, we are using the dependency injection to use the formbuilder.

    this.signupForm=frmbuilder.group(Formcontrols collection)


    This line of code takes the form control collection and groups into the formbuilder.

  3. The next portion is to define the controls in the formbuilder and group them to assign it to the signupform form.

    fname:new FormControl(),

Here, we are declaring the fname to be of type FormControl() and assigning to the fname property which will be our form control name in the HTML. Here, we can specify the initial value of our form controller and add some validators in it (we can see that in the next section).

This is all of the above code. Now, it’s time to tie up these controls in the component to our template, i.e., our HTML. Let’s just check the following snippet.

  1. <div>  
  2.   <form [formGroup]='signupForm' (ngSubmit)="PostData(signupForm)">  
  3.       <div class="form-container">  
  4.           <div class="row columns">  
  5.    <div>  
  6.     <input type="text" formControlName='fname' placeholder="Your First name">  
  7.     </div>  
  8.     <div>  
  9.     <br>  
  10.     <input type="text" formControlName='lname' placeholder="Your Last name">  
  11.   </div>  
  12.     <br>  
  13.     <div><input type="text" formControlName='Emailid' placeholder="Your Email id"></div>  
  14.     <br>  
  15.     <div>  
  16.     <input type="Password" formControlName='userpassword' placeholder="Your password">  
  17.   </div>  
  18.   <br>  
  19.   <div>  
  20. <input type="Submit" value="Post Data" >  
  21.   </div>  
  22.   </div>  
  23.   </div>  
  24.   </form>  
  25. </div>  

In these, we have two things to keep in mind in order to understand how binding of the controls takes place.

  1. <form [formGroup]='signupForm' (ngSubmit)="PostData(signupForm)">  
  1. In above code, we are binding the signupform to the formGroup directive

  2. Now, we have linked the signupform to the formgroup we can access the formcontrol values inside the template

  3. <input type="text" formControlName='fname' placeholder="Your First name">

    We have used the formControlName directive to map the element in the template to the property in the component
  1. We are using Angular ngSubmit directive to the post data method in the component which will be called on Button click which logs all the values of the Form Controls In the Template

Validations with Reactive forms

Now, the most important part of any form is to add the validations in the application. Let’s see how we can add the validation in the form. For that, let's check the formcontrol in the component.

When we do the fname:new FormControl(), the first argument in the FormControl is the initial value and the second value is the Validations that we can add there.

The only change in the component would be like below.

  1. this.signupForm= frmbuilder.group({  
  2.   fname:['',Validators.compose([Validators.required,Validators.maxLength(15),Validators.minLength(1)])],  
  3.   lname:['',[Validators.required,Validators.maxLength(19)]],  
  4.   Emailid:['',[Validators.required,Validators.email]],  
  5.   userpassword:['',Validators.required]  
  6. })  

Here, we are adding the Validators for the fields in the application. As we know, there can be more than one validations for the controls so we can add them in two ways - first, for single validations, we can use single validator and for the multiple validations, we can use the Validators.compose(list of validators separated by ,).

Showing the Error Message

  1. <div>  
  2.   <form [formGroup]='signupForm' (ngSubmit)="PostData(signupForm)">  
  3.       <div class="form-container">  
  4.           <div class="row columns">  
  5.    <div>  
  6.     <input type="text" formControlName='fname' name='fname' id='fname' placeholder="Your First name">  
  7.   
  8.     <div *ngIf="signupForm.controls['fname'].touched && !signupForm.controls['fname'].valid">  
  9.         <span *ngIf="signupForm.controls['fname'].hasError('required') ">  
  10.             First name is required  
  11.             </span>  
  12.             <span *ngIf="signupForm.controls['fname'].hasError('minlength') ">  
  13.              Min length is 1  
  14.             </span>  
  15.             <span *ngIf="signupForm.controls['fname'].hasError('maxlength') ">  
  16.             max length is 15  
  17.         </span>  
  18.     </div>  
  19.     </div>  
  20.     <div>  
  21.     <br>  
  22.     <input type="text" formControlName='lname' placeholder="Your Last name">  
  23.   
  24.     <div *ngIf="signupForm.controls['lname'].touched && !signupForm.controls['lname'].valid">  
  25.         <span *ngIf="signupForm.controls['lname'].hasError('required') ">  
  26.             Last name is required  
  27.             </span>  
  28.             <span *ngIf="signupForm.controls['lname'].hasError('minlength') ">  
  29.              Min length is 1  
  30.             </span>  
  31.             <span *ngIf="signupForm.controls['lname'].hasError('maxlength') ">  
  32.             max length is 15  
  33.         </span>  
  34.     </div>  
  35.   </div>  
  36.     <br>  
  37.     <div><input type="text" formControlName='Emailid' placeholder="Your Email id"></div>  
  38.     <div *ngIf="signupForm.controls['Emailid'].touched && !signupForm.controls['Emailid'].valid">  
  39.         <span *ngIf="signupForm.controls['Emailid'].hasError('required') ">  
  40.            Email ID is needed  
  41.              </span>  
  42.             
  43.       <span *ngIf="signupForm.controls['Emailid'].hasError('email') ">  
  44.            Invalid Email ID  
  45.             </span>  
  46.                        
  47.     </div>  
  48.     <br>  
  49.     <div>  
  50.     <input type="Password" formControlName='userpassword' placeholder="Your password">  
  51.   </div>  
  52.   <br>  
  53.   <div>  
  54. <input type="Submit" value="Post Data" [disabled]='!signupForm.valid' >  
  55.   </div>  
  56.   </div>  
  57.   </div>  
  58.   </form>  
  59. </div>  

In the above code snippet, we are showing the error messages when the field is touched and entered value.

  1. <div *ngIf="signupForm.controls['fname'].touched && !signupForm.controls['fname'].valid">  
  2.      <span *ngIf="signupForm.controls['fname'].hasError('required') ">  
  3.          First name is required  
  4.          </span>  
  5.          <span *ngIf="signupForm.controls['fname'].hasError('minlength') ">  
  6.           Min length is 1  
  7.          </span>  
  8.          <span *ngIf="signupForm.controls['fname'].hasError('maxlength') ">  
  9.          max length is 15  
  10.      </span>    </div>  

Here, we have listed all the validators that we have applied in the component. To check if the control is failing any validation, we have added the code.

  1. <div *ngIf="signupForm.controls['fname'].touched && !signupForm.controls['fname'].valid">  

This div will be displayed only if the fname is touched and it is valid. In that div, we have other section to display the errors, such as -required and min length and max length. We use ngIf directive here to display the proper error messages.

This was all about the Reactive forms and their validation.

References

  1. Angular official site(https:\\Angular.io\)
  2. https:\\Rangle.io\