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

Template driven form validation in Angular

In this tutorial, we will learn template-driven form validation in Angular. It is very common that the users will make mistakes when filling out the web form. This is where the validations come into play. The validation module must ensure that the user has provided accurate and complete information in the form fields. We must display the validation error messages to the users, disable the submit button until validation. In this tutorial, we will look at how validations are handled in Template-driven forms in Angular and learn how to use the Angular built-in validators.

This tutorial is a continuation of the Angular template-driven forms tutorial, where we built a simple form. In the next tutorial, we learned how to set the values to the form fields. We suggest you read those tutorials if you are new to Template-driven forms in Angular

Template-driven Form Validation

Validations in Template-driven forms are provided by the Validation directives. The Angular Forms Module comes with several built-in validators. You can also create your own custom Validator.

Template

Consider the following template-driven form. It has firstname ,lastname, email, gender & istoc form fields.

                              

<form #contactForm="ngForm" (ngSubmit)="onSubmit(contactForm)">
 
  <p>
    <label for="firstname">First Name </label>
    <input type="text" id="firstname" name="firstname" [(ngModel)]="contact.firstname">
  </p>
 
  <p>
    <label for="lastname">Last Name </label>
    <input type="text" id="lastname" name="lastname" [(ngModel)]="contact.lastname">
  </p>
 
  <p>
    <label for="email">email </label>
    <input type="text" id="email" name="email" [(ngModel)]="contact.email">
  </p>
 
  <p>
    <label for="gender">Geneder </label>
    <input type="radio" value="male" id="gender" name="gender" [(ngModel)]="contact.gender"> Male
    <input type="radio" value="female" id="gender" name="gender" [(ngModel)]="contact.gender"> Female
  </p>
 
  <p>
    <label for="isToc">Accept TOC</label>
    <input type="checkbox" id="isToc" name="isToc" [(ngModel)]="contact.isToc">
  </p>
 
  <p>
    <button type="submit">Submit</button>
  </p>
 
</form>
                            
                        

Component Class

                              
 
import { Component, ViewChild, ElementRef, OnInit } from '@angular/core';
import { NgForm } from '@angular/forms';
 
@Component,({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit  {
  title = 'Template driven forms';
 
  @ViewChild,('contactForm',null) contactForm: NgForm;
 
  contact:contact;
 
  ngOnInit() {
 
    this.contact = { 
      firstname:"",
      lastname:"",
      gender:"male",
      isToc:true,
      email:"",
    };
 
  }
 
  onSubmit() {
    console.log(this.contactForm.value);
  }
 
}
 
export class contact {
  firstname:string;
  lastname:string;
  gender:string;
  isToc:boolean;
  email:string;
} 
 
 
                            
                        

Disabling the Browser validation

First, we need to disable browser validator interfering with the Angular validator. To do that we need to add novalidate attribute on <form> element as shown below

                              
 
<form #contactForm="ngForm" (ngSubmit)="onSubmit(contactForm)" novalidate>
                            
                        

Built-in Validators

The Built-in validators use the HTML5 validation attributes like required, minlength, maxlength & pattern. Angular interprets these validation attributes and add the validator functions to FormControl instance.

Adding in Built-in Validators

Required Validation

The required validator returns true only if the form control has non-empty value entered. Let us add this validator to all fields

                              

<input type="text" id="firstname" name="firstname" required [(ngModel)]="contact.firstname">
 
                            
                        

Minlength Validation

This 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.

                              

 
<input type="text" id="firstname" name="firstname" required minlength="10" [(ngModel)]="contact.firstname">
 
                            
                        

Maxlength Validation

This Validator requires that the number of characters must not exceed the value of the attribute.

                              
 
<input type="text" id="lastname" name="lastname" required maxlength="15" [(ngModel)]="contact.lastname">
 
                            
                        

Pattern Validation

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

                              

<input type="text" id="lastname" name="lastname" required maxlength="15" 
    pattern="^[a-zA-Z]+$" [(ngModel)]="contact.lastname">
                            
                        

Email Validation

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

                              

<input type="text" id="email" name="email" required email [(ngModel)]="contact.email">
                            
                        

Disable Submit button

Now, we have successfully added the validators. You will notice that the click submit button still submits the form.

We need to disable the submit button if our form is not valid.

Angular forms module keep track of the state of our form and each of its form elements. These states are exposed to the user through FormGroup, FormArray & FormControl objects.

We get the reference to the top-level FormGroup instance by creating a template variable and bind it to ngForm. We have already done it when we had added the #contactForm="ngForm" in our form tag.

The FormGroup has a valid property, which is set to true if all of its child controls are valid. We use it to set the disabled attribute of the submit button.

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

So long ascontactForm.valid remains false, the submit button remains disabled.

Displaying the Validation/Error messages

We need to provide a short and meaningful error message to the user.

Angular creates a FormControl for each and every field, which has ngModel directive applied. The FormControl 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 We can use the contactForm.controls.firstname.valid to find out if the firstname is valid.

The other way is to create a new local variable for each FormControl For Example, the following firstname="ngModel" creates the firstname variable with the FormControl instance.

                              


<input type="text" id="firstname" name="firstname" required minlength="10" 
            #firstname="ngModel" [(ngModel)]="contact.firstname">
 
                            
                        

Now, we have a reference to the firstname FormControl instance, we can check its status. We use the valid property to check if the firstname has any errors.

valid: returns either invalid status or null which means a valid status

                              

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

Why check dirty and touched?

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 ” “Invalid First Name” ” 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)">
  Invalid First Name
  <div *ngIf="firstname.errors.required">
     First Name is required
  </div>
  <div *ngIf="firstname.errors.minlength">
    First Name Minimum Length is {{firstname.errors.minlength?.requiredLength}}
  </div>
</div>
 
                            
                        

Note that the minlength validators return the {{firstname.errors.minlength?.requiredLength}}, which we use the display the error message.

Final Template

                              
 
<form #contactForm="ngForm" (ngSubmit)="onSubmit(contactForm)" novalidate>
 
  <p>
    <label for="firstname">First Name </label>
    <input type="text" id="firstname" name="firstname" required minlength="10" #firstname="ngModel"
      [(ngModel)]="contact.firstname">
  </p>
  <div *ngIf="!firstname?.valid && (firstname?.dirty || firstname?.touched)" class="error">
    <div *ngIf="firstname.errors.required">
      First Name is required
    </div>
    <div *ngIf="firstname.errors.minlength">
      First Name Minimum Length is {{firstname.errors.minlength?.requiredLength}}
    </div>
  </div>
 
  <p>
    <label for="lastname">Last Name </label>
    <input type="text" id="lastname" name="lastname" required maxlength="15" #lastname="ngModel" 
            pattern="^[a-zA-Z]+$"  [(ngModel)]="contact.lastname">
  </p>
  <div *ngIf="!lastname?.valid && (lastname?.dirty || lastname?.touched)" class="error">
    <div *ngIf="lastname.errors.required">
      Last Name is required
    </div>
    <div *ngIf="lastname.errors.maxlength">
      Last Name Minimum Length is {{lastname.errors.maxlength?.requiredLength}}
    </div>
    <div *ngIf="lastname.errors.pattern">
      Only characters are allowed
    </div>
  </div>
 
 
 
  <p>
    <label for="email">email </label>
    <input type="text" id="email" name="email" required email #email="ngModel" [(ngModel)]="contact.email">
  </p>
  <div *ngIf="!email?.valid && (email?.dirty || email?.touched)" class="error">
    <div *ngIf="email.errors.required">
      Email is required
    </div>
    <div *ngIf="email.errors.email">
      Invalid Email Address
    </div>
  </div>
 
  <p>
    <label for="gender">Geneder </label>
    <input type="radio" value="male" id="gender" name="gender" #gender="ngModel" required [(ngModel)]="contact.gender">
    Male
    <input type="radio" value="female" id="gender" name="gender" #gender="ngModel" required
      [(ngModel)]="contact.gender"> Female
  </p>
  <div *ngIf="!gender?.valid && (gender?.dirty || gender?.touched)" class="error">
    <div *ngIf="gender.errors.required">
      Gender is required
    </div>
  </div>
 
 
  <p>
    <label for="isToc">Accept TOC</label>
    <input type="checkbox" id="isToc" name="isToc" required #isToc="ngModel" [(ngModel)]="contact.isToc">
  </p>
  <div *ngIf="!isToc?.valid && (isToc?.dirty || isToc?.touched)" class="error">
    <div *ngIf="isToc.errors.required">
      Please accept the TOC
    </div>
  </div>
 
  <p>
    <button type="submit" [disabled]="!contactForm.valid">Submit</button>
  </p>
 
  <p>{{contactForm.valid}} </p>
 
</form>
                            
                        

Summary

Angular template-driven form validation uses the directives known as validators. The validators handle form validations and display validation messages. The Angular comes up with several built-in validators for this purpose. They are minlength , maxlength, email, pattern, required , etc.