Angular Js

How to manage Validation in Angular Template-driven forms?

How to manage Validation in Angular Template-driven forms?

manage Validation in Angular Template-driven forms

This Article helps you to Understand, How to manage Validation in Angular Template-driven forms?


In the template-driven approach we define the validators via directives and HTML5 attributes in our template itself


// ngSubmit- is an output event binding which calls a function on our component called
// onSubmit when the user clicks the submit button.
<form (ngSubmit)="onSubmit()" #f="ngForm">


// Can add the HTML required attribute
// Can use a pattern validator,

<input type="email"
     class="form-control"
     name="email"
     [(ngModel)]="model.email"
     required
     pattern="[^ @]*@[^ @]*">


// Can use a length validator,
<input type="password"
       class="form-control"
       name="password"
       [(ngModel)]="model.password"
       required
       minlength="8">

</form>


Validation Styling
We can access each model form controls state similarly to model-driven forms by going through the top-level form group. Through its form property, the ngForm directive makes the top-level FormGroup available to us.


<pre>Valid? {{f.form.controls.email?.valid}}</pre>
<pre>Dirty? {{f.form.controls.email?.dirty}}</pre>
<pre>Touched? {{f.form.controls.email?.touched}}</pre>

The ? is called the elvis operator, it means:
Only try to call the property on the right of ? if the property on the left of ? is not null

We use the elvis operator in template-driven forms because the controls could occasionally be null while Angular is creating the page. Because the models are already constructed in our component by the time the HTML form is displayed on the page, we don't need to use this for model-driven forms.


Let’s add validation styling
In the code below, an incorrect input control has a red border, whereas a legitimate one has a green border.

<form (ngSubmit)="onSubmit()" #f="ngForm">
<div class="form-group"
  [ngClass]="{
   'has-danger': f.form.controls.email?.invalid && (f.form.controls.email?.dirty || f.form.controls.email?.touched),
  'has-success': f.form.controls.email?.valid && (f.form.controls.email?.dirty || f.form.controls.email?.touched)
  }">
  <label>Email</label>
  <input type="email"
         class="form-control"
         name="email"
         [(ngModel)]="model.email"
         required
         pattern="[^ @]*@[^ @]*">
</div>
</form>


Shorter Validation Expressions (to refer form elements in template itself)
Method 1:
We do have a shorthand for the controls property provided by the NgForm directive,
so we can write f.controls.email?.valid instead of f.form.controls.email?.valid. Reason being f itself represent FormControl the 'form' at top level.


Method 2:
However, using the ngModel directive gives us a far quicker option.
We may use a local template reference variable to access the instance of our ngModel directive as seen in the following example:


<input ... [(ngModel)]="model.email" #email="ngModel"> </input>


Now, In our template, we can then use our local variable email.
NgModel stored a reference of each element / control / FormControl in its control property, which we can now access in the template by using the syntax email.control.touched. This is because NgModel created the FormControl instance in the first place to manage the template form control.


<form (ngSubmit)="onSubmit()" #f="ngForm">
<div class="form-group"
     [ngClass]="{
      'has-danger': email.invalid && (email.dirty || email.touched), (1)
      'has-success': email.valid && (email.dirty || email.touched)
 }">
  <label>Email</label>
  <input type="email"
         class="form-control"
         name="email"
         [(ngModel)]="model.email"
         required
         pattern="[^ @]*@[^ @]*"
         #email="ngModel"> (2)
</div>
</form>


Now, we can use the local variable 'email' in the template to directly access its form control. This so because, on this input control, we establish a template local variable that points to the instance of the ngModel directive.

We can simply reuse the same ngClass syntax, as long as we gave our local reference variables the same names as we gave our form controls in the model-driven version of this form:


<div class="form-group"
  [ngClass]="{
    'has-danger': email.invalid && (email.dirty || email.touched),
    'has-success': email.valid && (email.dirty || email.touched)
}">


Validation Messages
We can employ the exact same technique for form validation messages as we did for model-driven/react forms. We can use precisely the same HTML in our template-driven forms as long as we named the local reference variables the same as the form controls in the model-driven technique, as follows:


<form (ngSubmit)="onSubmit()" #f="ngForm">
<div class="form-group"
  [ngClass]="{
    'has-danger': email.invalid && (email.dirty || email.touched),
    'has-success': email.valid && (email.dirty || email.touched)
}">
  <label>Email</label>
 <input type="email"
         class="form-control"
         name="email"
         [(ngModel)]="model.email"
         required
         pattern="[^ @]*@[^ @]*"
         #email="ngModel"> (2)
</div>
<div class="form-control-feedback" *ngIf="email.errors && (email.dirty || email.touched)">
  <p *ngIf="email.errors.required">Email is required</p>
  <p *ngIf="email.errors.minlength">Email must contain at least the @ character</p>
</div>

<button class="btn btn-primary" type="submit" [disabled]="!f.valid">
      Submit
   </button>
</form>


Resetting the Form
By using the function reset() on our myform model, we reset the form using the model-driven methodology. In our template-driven approach, we must accomplish the same thing, but our component does not provide us with access to the underlying form model. Through the local reference variable f.form in our template, we are the only ones with access to it.
By utilising a ViewChild decorator, we can obtain a reference to the ngForm instance in our component code.


import { Component, ViewChild } from "@angular/core";
import { NgForm } from "@angular/forms";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"],
})
export class AppComponent {
  @ViewChild("f", { static: false }) signupForm: NgForm
  user = {
    username: "",
    email: "",
  };
  submitted = false;

  onSubmit() {
    console.log(this.signupForm);
    this.submitted = true;   
    this.user.email = this.signupForm.value.userData.email; 
// Reset all form fields
    this.signupForm.reset();
  }
}

Now, when we submit the form, it clears all the fields and resets the states of the form controls (by calling reset method on our form), restoring any styling or errors from the form's validation to their original perfect state.



Related Post

About Us

Community of IT Professionals

A Complete IT knowledgebase for any kind of Software Language, Development, Programming, Coding, Designing, Networking, Hardware and Digital Marketing.

Instagram