Validations In Reactive Forms In Angular

Validations In Reactive Forms In Angular

In this article, We will learn how angular reactive forms validation works. Validation is one of the most common tasks undertaken when creating a form. We will demonstrate how to create Reactive Forms and use built-in validators. In the following article, We will learn how to use Reactive Forms to develop custom validators.

In the Template-driven Forms article, we looked at how validation works. The majority of the principles covered in that tutorial apply here as well.

Validators in Reactive Forms

What is a Validator

A Validator is a function that checks and returns a list of errors for a FormControl, FormGroup, or FormArray instance. Validation has passed if the Validator returns a null value.

How to add a Validator to Reactive Forms

The validators are set as the second and third arguments in the component class's FormControl, FormGroup, or FormArray. A collection of sync validators is the second argument, and a collection of async validators is the third.

Validation is performed and results are returned promptly by sync validators. If no errors are discovered, they either return null or a list of errors.

Validators that are asynchronous: return a Promise or an Observable. If no errors are discovered, they either return null or a list of errors.

Built-in Validators

The Angular ReactiveForms Module comes with a number of built-in validators. They are required, including minlength, maxlength, and pattern, among other things.

Reactive Forms Validation Example

In the previous tutorial, W learned how to develop Angular Reactive Forms. To that example, we'll now add some of the built-in validators.

Model

The contactForm model from the last instruction is shown here.

contactForm = new FormGroup({
  firstname: new FormControl(''),
  lastname: new FormControl(''),
  email:new FormControl(''),
  gender: new FormControl(''),
  isMarried: new FormControl(''),
  country: new FormControl(''),
  address:new FormGroup({
    city: new FormControl(''),
    street: new FormControl(''),
    pincode:new FormControl('')
  })
})

Disabling the Browser validation

To begin, we'll disable the browser validator by adding the novalidate attribute to the <form> element, as shown below. If this attribute is present, the form will not be validated when it is submitted using the built-in HTML5 validation.

<form contactform="" formgroup="" ngsubmit="" novalidate="" onsubmit="">

Adding in Built-in Validators

As previously said, Angular comes with multiple built-in validators out of the box.

Required Validator

The necessary validator is a sync validator, which returns true only if a non-empty value is entered in the formcontrol. The Sync Validator is given as the FormControl's second argument.

firstname: new FormControl('',[Validators.required]),

Minlength Validator

The control value for the Minlength validator must not be fewer than the amount of characters given in the validator.

The minlength validator, for example, verifies that the firstname value has at least 10 characters.

firstname: new FormControl('',[Validators.required,Validators.minLength(10)]),

Maxlength Validator

The amount of characters in this Validator must not exceed the value set in the validator.

lastname: new FormControl('',[Validators.maxLength(15)]),

Pattern Validator

The control value must match the regex pattern specified in the property for this Validator to work. The pattern [a-zA-Z]+$, for example, ensures that only letters are allowed (even spaces are not allowed). Let's put this pattern to work on the lastName.

lastname: new FormControl('',[Validators.maxLength(15), Validators.pattern("^[a-zA-Z]+$")]),

Email Validator

The control value for this Validator must be a genuine email address. This is what we do with the email field.

email:new FormControl('',[Validators.email,Validators.required]),

Our final contactForm will look like this after we've added all of the validators.

contactForm = new FormGroup({
  firstname: new FormControl('',[Validators.required,Validators.minLength(10)]),
  lastname: new FormControl('',[Validators.required, Validators.maxLength(15), Validators.pattern("^[a-zA-Z]+$")]),
  email:new FormControl('',[Validators.email,Validators.required]),
  gender: new FormControl('',[Validators.required]),
  isMarried: new FormControl('',[Validators.required]),
  country: new FormControl('',[Validators.required]),
  address:new FormGroup({
    city: new FormControl('',[Validators.required]),
    street: new FormControl('',[Validators.required]),
    pincode:new FormControl('',[Validators.required])
  })
})

Disable Submit button

The validators have been successfully inserted. If our form isn't valid, we'll need to block the submit button.

The FormGroup, FormControl, and FormArray instances in the Angular Forms API expose the state of the forms. The valid attribute of the FormGroup control is set to true if all of its child controls are valid.

The top-level FormGroup is represented by the contactForm. It's used to disable the submit button's disabled property.

<button contactform.valid="" disabled="" type="submit">Submit</button>

Displaying the Validation/Error messages

We must give the user with a concise and meaningful error message. This is accomplished by making use of the error object returned by the FormControl instance.

A FormControl instance is connected with each form element. It reveals the state of form elements such as valid, dirty, touched, and so on.

You can retrieve the reference to the FormControl in one of two methods.

The contactForm variable is one option. To check if the firstname is legitimate, we can use contactForm.controls.firstname.valid.

<div ngif="!contactForm.controls.firstname?.valid && (contactForm.controls.firstname?.dirty
  ||contactForm.controls.firstname?.touched)">
    First Name is not valid
</div>

Another option is to define a getter function in the component class for each FormControl instance.

get firstname() {
   return this.contactForm.get('firstname');
}

and then use it as follows in the template

<div ngif="!firstname.valid && (firstname.dirty ||firstname.touched)">
    First Name is not valid
</div>

Dirty & touched

We check for dirty and touched items in addition to eligible items. Because we don't want the program to show the error the first time the form is presented. Only after the user has attempted to change the value should errors be displayed. The dirty and touched properties help to do us.

dirty: If the user has changed the value in the UI, the control is dirty.
touched: If the user has triggered a blur event on a control, it is touched.

Error message

"First Name is not valid" is a useless error message. There are two validators for the firstname. minlength and needed

The errors object is updated with any errors generated by the unsuccessful validation. The errors object returns either the error object or null if no errors exist.
<div ngif="!firstname?.valid && (firstname?.dirty ||firstname?.touched)">
  <div firstname.errors.required="" hidden="">
    First Name is required
  </div>
  <div firstname.errors.minlength="" hidden="">
    Min Length is 10
  </div>
</div>

The following code is complete code of the app.component.ts file
import { Component, ViewChild, ElementRef } from '@angular/core';
import { FormGroup, FormControl, Validators } from '@angular/forms'
 
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Angular Reactive forms';
 
 
  contactForm = new FormGroup({
    firstname: new FormControl('',[Validators.required,Validators.minLength(10)]),
    lastname: new FormControl('',[Validators.required, Validators.maxLength(15), Validators.pattern("^[a-zA-Z]+$")]),
    email:new FormControl('',[Validators.email,Validators.required]),
    gender: new FormControl('',[Validators.required]),
    isMarried: new FormControl('',[Validators.required]),
    country: new FormControl('',[Validators.required]),
    address:new FormGroup({
      city: new FormControl('',[Validators.required]),
      street: new FormControl('',[Validators.required]),
      pincode:new FormControl('',[Validators.required])
    })
  })
 
  get firstname() {
    return this.contactForm.get('firstname');
  } 
 
  get lastname() {
    return this.contactForm.get('lastname');
  } 
 
  get email() {
    return this.contactForm.get('email');
  } 
 
  get gender() {
    return this.contactForm.get('gender');
  } 
 
  get isMarried() {
    return this.contactForm.get('isMarried');
  } 
 
  get country() {
    return this.contactForm.get('country');
  } 
 
  get city() {
    return this.contactForm.get("address").get('city');
  } 
 
  get street() {
    return this.contactForm.get("address").get('street');
  } 
 
  get pincode() {
    return this.contactForm.get("address").get('pincode');
  } 
 
 
  countryList: country[] = [
    new country("1", "India"),
    new country('2', 'USA'),
    new country('3', 'England')
  ];
 
 
 
 
  onSubmit() {
    console.log(this.contactForm.value);
  }
 
 
 
}
 
 
export class contact {
  firstname:string;
  lastname:string;
  gender:string;
  isMarried:boolean;
  country:string;
  address: {
    city:string;
    street:string;
    pincode:string;
  }
} 
 
 
export class country {
  id: string;
  name: string;
 
  constructor(id: string, name: string) {
    this.id = id;
    this.name = name;
  }
}

The following code is complete code of the app.component.html file
<form [formGroup]="contactForm" (ngSubmit)="onSubmit()" novalidate>
  <p>
    <label>First Name </label>
    <input formcontrolname="firstname" id="firstname" name="firstname" type="text" />
  </p>
 
  <div ngif="!firstname?.valid && (firstname?.dirty ||firstname?.touched)">
    <div firstname.errors.required="" hidden="">
      First Name is required
    </div>
    <div firstname.errors.minlength="" hidden="">
      Min Length is 10
    </div>
  </div>
 
  <p>
    <label>Last Name </label>
    <input formcontrolname="lastname" id="lastname" name="lastname" type="text" />
  </p>
 
  <div ngif="!lastname.valid && (lastname.dirty ||lastname.touched)">
    <div hidden="" lastname.errors.pattern="">
      Only characters are allowed
    </div>
    <div hidden="" lastname.errors.maxlength="">
      Max length allowed is {{lastname.errors.maxlength?.requiredLength}} 
    </div>
    <div hidden="" lastname.errors.required="">
      Last Name is required
    </div>
  </div>
 
  <p>
    <label>Email </label>
    <input formcontrolname="email" id="email" name="email" type="text" />
  </p>
  <div ngif="!email.valid && (email.dirty ||email.touched)">
    <div email.errors.required="" hidden="">
      email is required
    </div>
    <div email.errors.email="" hidden="">
      invalid email id
    </div>
  </div>
 
 
  <p>
    <label>Geneder </label>
    <input formcontrolname="gender" id="gender" name="gender" type="radio" value="male" /> Male
    <input formcontrolname="gender" id="gender" name="gender" type="radio" value="female" /> Female
  </p>
  <div ngif="!gender.valid && (gender.dirty ||gender.touched)">
    <div gender.errors.required="" hidden="">
      gender is required
    </div>
  </div>
 
  <p>
    <label>Married </label>
    <input formcontrolname="isMarried" id="isMarried" name="isMarried" type="checkbox" />
  </p>
  <div ngif="!isMarried.valid && (isMarried.dirty ||isMarried.touched)">
    <div hidden="" ismarried.errors.required="">
      isMarried is required
    </div>
  </div>
 
 
  <p>
    <label>country </label>
    <select formcontrolname="country" id="country" name="country">
      <option c.id="" ngfor="let c of countryList" ngvalue="">
        {{c.name}}
      </option>
    </select>
  </p>
  <div ngif="!country.valid && (country.dirty ||country.touched)">
    <div country.errors.required="" hidden="">
      country is required
    </div>
  </div>
 
 
 
  <div formgroupname="address">
 
    <div class="form-group">
      <label>City</label>
      <input class="form-control" formcontrolname="city" name="city" type="text" />
    </div>
    <div ngif="!city.valid && (city.dirty ||city.touched)">
      <div city.errors.required="" hidden="">
        city is required
      </div>
    </div>
 
 
    <div class="form-group">
      <label>Street</label>
      <input class="form-control" formcontrolname="street" name="street" type="text" />
    </div>
    <div ngif="!street.valid && (street.dirty ||street.touched)">
      <div hidden="" street.errors.required="">
        street is required
      </div>
    </div>
 
    <div class="form-group">
      <label>Pin Code</label>
      <input class="form-control" formcontrolname="pincode" name="pincode" type="text" />
    </div>
    <div ngif="!pincode.valid && (pincode.dirty ||pincode.touched)">
      <div hidden="" pincode.errors.required="">
        pincode is required
      </div>
    </div>
 
  </div>
 
  <p>{{contactForm.valid}} </p>
 
  <p>
    <button contactform.valid="" disabled="" type="submit">Submit</button>
  </p>
 
 
</form>


Conclusion

We just learned how to validate Angular Reactive Forms.

I hope this article helps you and you will like it.👍

If you have any doubt or confusion then free to ask in comment section.

Post a Comment

Previous Post Next Post