ANGULAR
Complete Angular Tutorial For Beginners Introduction to Angular | What is Angular? Architecture Overview & Concepts of Angular How to Install Angular How to Create a new project in Angular Bootstrapping in Angular: How It Works Internally Angular Components Overview & Examples Data Binding in Angular Interpolation in Angular Property Binding in Angular Event Binding in Angular ngModel & Two way Data binding in Angular NgModelChange & Change Event in Angular Child/Nested Components in Angular angular directives angular ngFor directive ngSwitch, ngSwitchcase, ngSwitchDefa ult Angular Example How to use ngIf, else, then in Angular By example NgClass Example Conditionally apply class Angular ngStyle Directive Angular Trackby to improve ngFor Performance How to Create & Use Custom Directive In Angular Working with Angular Pipes How to Create Custom Pipe in Angular Formatting Dates with Angular Date Pipe Using Angular Async Pipe with ngIf & ngFor angular keyValue pipe Using Angular Pipes in Components or Services Angular Component Communication & Sharing Data Angular Pass data to child component Angular Pass data from Child to parent component Component Life Cycle Hooks in Angular Angular ngOnInit And ngOnDestroy Life Cycle hook Angular ngOnChanges life Cycle Hook Angular ngDoCheck Life Cycle Hook Angular Forms Tutorial: Fundamentals & Concep t s Angular Template-driven forms example How to set value in template-driven forms in Angular Angular Reactive Forms Example Using Angular FormBuilder to build Forms SetValue & PatchValue in Angular StatusChanges in Angular Forms ValueChanges in Angular Forms FormControl in Angular FormGroup in Angular Angular FormArray Example Nested FormArray Example Add Form Fields Dynamically SetValue & PatchValue in FormArray Angular Select Options Example in Angular Introduction to Angular Services Introduction to Angular Dependency Injection Angular Injector, @Injectable & @Inject Angular Providers: useClass, useValue, useFactory & useExisting Injection Token in Angular How Dependency Injection & Resolution Works in Angular Angular Singleton Service ProvidedIn root, any & platform in Angular @Self, @SkipSelf & @Optional Decorators Angular '@Host Decorator in Angular ViewProviders in Angular Angular Reactive Forms Validation Custom Validator in Angular Reactive Form Custom Validator with Parameters in Angular Inject Service Into Validator in Angular template_driven_form_validation_in_angular Custom Validator in Template Driven Forms in Angular Angular Async Validator Example Cross Field or Multi Field Validation Angular How to add Validators Dynamically using SetValidators in Angular Angular HttpClient Tutorial & Example Angular HTTP GET Example using httpclient Angular HTTP POST Example URL Parameters, Query Parameters, httpparams in Angular HttpClient Angular HTTPHeaders Example Understanding HTTP Interceptors in Angular Angular Routing Tutorial with Example Location Strategy in Angular Angular Route Params Angular : Child Routes / Nested Route Query Parameters in Angular Angular Pass Data to Route: Dynamic/Static RouterLink, Navigate & NavigateByUrl to Navigate Routes RouterLinkActive in Angular Angular Router Events ActivatedRoute in Angular Angular Guards Tutorial Angular CanActivate Guard Example Angular CanActivateChild Example Angular CanDeactivate Guard Angular Resolve Guard Introduction to Angular Modules or ngModule Angular Routing between modules Angular Folder Structure Best Practices Guide to Lazy loading in Angular Angular Preloading Strategy Angular CanLoad Guard Example Ng-Content & Content Projection in Angular Angular @input, @output & EventEmitter Template Reference Variable in Angular ng-container in Angular How to use ng-template & TemplateRef in Angular How to Use ngTemplateOutlet in Angular '@Hostbinding and @Hostlistener_in_Angular Understanding ViewChild, ViewChildren &erylist in Angular ElementRef in Angular Renderer2 Example: Manipulating DOM in Angular ContentChild and ContentChildren in Angular AfterViewInit, AfterViewChecked, AfterContentInit & AfterContentChecked in Angular Angular Decorators Observable in Angular using RxJs Create observable from a string, array & object in angular Create Observable from Event using FromEvent in Angular Using Angular observable pipe with example Angular Map Operator: Usage and Examples Filter Operator in Angular Observable Tap operator in Angular observable Using SwitchMap in Angular Using MergeMap in Angular Using concatMap in Angular Using ExhaustMap in Angular Take, TakeUntil, TakeWhile & TakeLast in Angular Observable First, Last & Single Operator in Angular Observable Skip, SkipUntil, SkipWhile & SkipLast Operators in Angular The Scan & Reduce operators in Angular DebounceTime & Debounce in Angular Delay & DelayWhen in Angular Using ThrowError in Angular Observable Using Catcherror Operator in Angular Observable ReTryWhen inReTry, ReTryWhen in Angular Observable Unsubscribing from an Observable in Angular Subjects in Angular ReplaySubject, BehaviorSubject & AsyncSubject in Angular Angular Observable Subject Example Sharing Data Between Components Angular Global CSS styles View Encapsulation in Angular Style binding in Angular Class Binding in Angular Angular Component Styles How to Install & Use Angular FontAwesome How to Add Bootstrap to Angular Angular Location Service: go/back/forward Angular How to use APP_INITIALIZER Angular Runtime Configuration Angular Environment Variables Error Handling in Angular Applications Angular HTTP Error Handling Angular CLI tutorial ng new in Angular CLI How to update Angular to latest version Migrate to Standalone Components in Angular Create Multiple Angular Apps in One Project Set Page Title Using Title Service Angular Example Dynamic Page Title based on Route in Angular Meta service in Angular. Add/Update Meta Tags Example Dynamic Meta Tags in Angular Angular Canonical URL Lazy Load Images in Angular Server Side Rendering Using Angular Universal The requested URL was not found on this server error in Angular Angular Examples & Sample Projects Best Resources to Learn Angular Best Angular Books in 2020

Angular Reactive Forms Validation

In this article, will explore how angular reactive forms validation works. One of the common tasks that is performed, while building a form is Validation. We will show you how to build Reactive Forms and apply Built-in validators. In the next tutorial, you will learn how to create custom validators in Reactive Forms.

We looked at how the validation works in the Template-driven Forms tutorial. Most of the concepts explained in that tutorial are equally applicable here.

Validators in Reactive Forms

What is a Validator

A Validator is a function that checks the instance of FormControl,FormGroup or a FormArray and returns a list of errors. If the Validator returns a null means that validation has passed

How to add a Validator to Reactive Forms

We configure the validators as the second and third argument to the FormControl, FormGroup or FormArray in the component class. The second argument is a collection of sync validators and the third argument is a collection of an async validators.

sync validators runs validations and returns immediately. They either return a list of errors or null if no errors found.

async validators: returns a Promise or Observable. They either return a list of errors or null if no errors are found.

Built-in Validators

The Angular ReactiveForms Module provides several Built-in validators out of the box. They are required, minlength, maxlength & pattern etc.

Reactive Forms Validation Example

W learned how to create Angular Reactive Forms in the previous tutorial. We will now add some of the built-in validators to that example.

Model

Here is the contactForm model from the previous tutorial.

                              

  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

First, we need to disable browser validator by adding the novalidate attribute to the <form> element as shown below. If this attribute is present then the form is not validated by the built-in HTML5 validation when submitted.

                              

<form [formGroup]="contactForm" (ngSubmit)="onSubmit()" novalidate>
                            
                        

Adding in Built-in Validators

The mentioned earlier, the Angular has provided several built-in validators out of the box.

Required Validator

The required validator is a sync validator, which returns true only if the formcontrol has a non-empty value entered. The second argument of the FormControl takes the Sync Validator.

                              

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

Minlength Validator

Minlength validator requires the control value must not have less number of characters than the value specified in the validator.

For Example, minlength validator ensures that the firstname value has at least 10 characters.

                              

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

Maxlength Validator

This Validator requires that the number of characters must not exceed the value specified in the validator.

                              

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

Pattern Validator

This Validator requires that the control value must match the regex pattern provided in the attribute. For example, the pattern ^[a-zA-Z]+$ ensures that the only letters are allowed (even spaces are not allowed). Let us apply this pattern to the lastName

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

Email Validator

This Validator requires that the control value must be a valid email address. We apply this to the email field

                              

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

After adding all the validators, our final contactForm will look like this.

                              

  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

We have successfully added the validators. Now, we need to disable the submit button if our form is not valid.

The Angular Forms API exposes the state of the forms through the FormGroup, FormControl & FormArray instances. The FormGroup control has a property valid, which is set to true if all of its child controls are valid.

The contactForm represents the top-level FormGroup. We use it to set the disabled attribute of the submit button.

                              
<button type="submit" [disabled]="!contactForm.valid">Submit</button>
                            
                        

Displaying the Validation/Error messages

We need to provide a short and meaningful error message to the user. We do that by using the error object returned by the FormControl instance

Every form element has a FormControl instance associated with it. It exposes the state of form element like valid, dirty, touched etc.

There are two ways in which you can get the reference to the FormControl.

One way is to use the contactForm variable. We can use contactForm.controls.firstname.valid to find out if the firstname is valid.

                              

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

The other way to is to define getter function for each FormControl instance in the component class.

                              

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

and then use it in the template as follows

                              

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

Dirty & touched

Apart from checking valid we are also checking for the dirty & touched. Because we do not want the application to display the error when the form is displayed for the first time. We want to display errors only after the user has attempted to change the value. The dirty & touched properties help us do that.

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

Error message

The error message “First Name is not valid” is not helpful. The firstname has two validators. required and minlength

Any errors generated by the failing validation is updated in the errors object. The errors object returns the error object or null if there are no errors.

                              

<div
*ngIf="!firstname?.valid && (firstname?.dirty ||firstname?.touched)">
<div [hidden]="!firstname.errors.required">
      First Name is required
    </div>
    <div [hidden]="!firstname.errors.minlength">
      Min Length is 10
</div>
</div>
 
                            
            

Final Code

app.component.ts

                              
 
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;
  }
}
 
 
                            
                        
app.component.html
                              
 
<form [formGroup]="contactForm" (ngSubmit)="onSubmit()" novalidate>
 
  <p>
    <label for="firstname">First Name </label>
    <input type="text" id="firstname" name="firstname" formControlName="firstname">
  </p>
 
  <div
    *ngIf="!firstname?.valid && (firstname?.dirty ||firstname?.touched)">
    <div [hidden]="!firstname.errors.required">
      First Name is required
    </div>
    <div [hidden]="!firstname.errors.minlength">
      Min Length is 10
    </div>
  </div>
 
  <p>
    <label for="lastname">Last Name </label>
    <input type="text" id="lastname" name="lastname" formControlName="lastname">
  </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 for="email">Email </label>
    <input type="text" id="email" name="email" formControlName="email">
  </p>
  <div *ngIf="!email.valid && (email.dirty ||email.touched)">
    <div [hidden]="!email.errors.required">
      email is required
    </div>
    <div [hidden]="!email.errors.email">
      invalid email id
    </div>
  </div>
 
 
  <p>
    <label for="gender">Geneder </label>
    <input type="radio" value="male" id="gender" name="gender" formControlName="gender"> Male
    <input type="radio" value="female" id="gender" name="gender" formControlName="gender"> Female
  </p>
  <div *ngIf="!gender.valid && (gender.dirty ||gender.touched)">
    <div [hidden]="!gender.errors.required">
      gender is required
    </div>
  </div>
 
  <p>
    <label for="isMarried">Married </label>
    <input type="checkbox" id="isMarried" name="isMarried" formControlName="isMarried">
  </p>
  <div *ngIf="!isMarried.valid && (isMarried.dirty ||isMarried.touched)">
    <div [hidden]="!isMarried.errors.required">
      isMarried is required
    </div>
  </div>
 
 
  <p>
    <label for="country">country </label>
    <select id="country" name="country" formControlName="country">
      <option [ngValue]="c.id" *ngFor="let c of countryList">
        {{c.name}}
      </option>
    </select>
  </p>
  <div *ngIf="!country.valid && (country.dirty ||country.touched)">
    <div [hidden]="!country.errors.required">
      country is required
    </div>
  </div>
 
 
 
  <div formGroupName="address">
 
    <div class="form-group">
      <label for="city">City</label>
      <input type="text" class="form-control" name="city" formControlName="city">
    </div>
    <div *ngIf="!city.valid && (city.dirty ||city.touched)">
      <div [hidden]="!city.errors.required">
        city is required
      </div>
    </div>
 
 
    <div class="form-group">
      <label for="street">Street</label>
      <input type="text" class="form-control" name="street" formControlName="street">
    </div>
    <div *ngIf="!street.valid && (street.dirty ||street.touched)">
      <div [hidden]="!street.errors.required">
        street is required
      </div>
    </div>
 
    <div class="form-group">
      <label for="pincode">Pin Code</label>
      <input type="text" class="form-control" name="pincode" formControlName="pincode">
    </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 type="submit" [disabled]="!contactForm.valid">Submit</button>
  </p>
 
 
</form>
 
 
 
 
<!-- <div ngModelGroup="address">
 
  <p>
    <label for="city">City</label>
    <input type="text" id="city" name="city">
  </p>
 
  <p>
    <label for="street">Street</label>
    <input type="text" id="street" name="street">
  </p>
  <p>
    <label for="pincode">Pin Code</label>
    <input type="text" id="pincode" name="pincode">
  </p>
 
</div> -->