Angular 2 - Part 9 [Template-Driven Form]


In this tutorial we will create a template-driven form which will contain username, email, password and gender fields. which is as shown below:


here is the template-driven.html template file for this form:

<h2>Template Driven</h2>
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
  <div ngModelGroup = "userData">
    <div class="form-group">
      <label for="username">Username: </label>
      <input type="text" class="form-control"
             minlength="4"
             id="username"
             [(ngModel)]="user.username" name="username" required
             >
    </div>
    
    <div class="form-group">
      <label for="email">Email: </label>
      <input type="text" class="form-control"
             pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"
             id="email"
             [(ngModel)]="user.email" name="email" required
            >
    </div>
  </div>
  <div class="form-group">
    <label for="password">Password: </label>
    <input type="password" class="form-control"
           id="password"
           [(ngModel)]="user.password" name="password" required>
  </div>
  <div class="radio" *ngFor="let g of genders">
    <label>
      <input type="radio" [(ngModel)] = "user.gender" name="gender" [value]="g"> 
       {{g}}
    </label>
  </div>
  <button type="submit" class="btn btn-primary" >Submit</button>
</form>

Now let create a component for this form
template-driven.component.ts




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

@Component({
  selector: 'app-template-driven',
  templateUrl: './template-driven.component.html',
  styleUrls: ['./template-driven.component.css']
})
export class TemplateDrivenComponent{

  user = {
    username:"Yubraj",
    email:"yubraj@gmail.com",
    password:"asdfasdf",
    gender: "male"
  }
  
  genders = ["male", "female"];

  constructor() { }

  onSubmit(form: NgForm){
    console.log(form.value);
  }
}



What we did here is:
1. We created a html template
2. then we bind the html input with the user object which is in the component.
3. [(ngModel)]="user.username" .. is used to bind using two way data binding in the form
4. in the form we use (ngSubmit)="onSubmit()" to submit the form and #f is used to hold the form.
5. once submitting the form we will display the form value in the console.

What we need to implement is:
1. Only allow submission only when all the form data is valid.
2. show errors in the forms.

lets add some more attributes in the input fields i.e. #username, #email in order to represent the given field so we can show errors once it has been changed. Before that let us know that angular will add its own classes in the input field when running it, which are ng-valid if the form is valid and ng-invalid if the form is invalid as well as ng-dirty if the form value is changed and ng-touched if the form input
is touched or selected. which is as shown below:



so we modify the class ng-invalid and ng-valid which is used to highlight the input field if the data is not valid.

template-driven.component.css

.ng-invalid{ border-color: red; }
.ng-valid{  border-color: forestgreen; }

so once the input is invalid the border color will turn to red and on valid it will turn to green.


Adding the error message in the form:
we will add this line of code in the form to show the error in the form for each fields

<div class="alert alert-danger" role="alert" *ngIf="!username.valid">Invalid username</div>

here #username is used to reference the username input field in the form. So once it is invalid this above line will be displayed.  Similarly we can also make the submit button disabled if the form which is referenced by f. by this way:
<button type="submit" class="btn btn-primary" [disabled]="!f.valid">Submit</button>

lets check it out all together:

template-driven.component.html

<h2>Template Driven</h2>
<form (ngSubmit)="onSubmit(f)" #f="ngForm">
  <div ngModelGroup = "userData">
    <div class="form-group">
      <label for="username">Username: </label>
      <input type="text" class="form-control"
             minlength="4"
             id="username"
             [(ngModel)]="user.username" name="username" required
             #username="ngModel">
    </div>
    <div class="alert alert-danger" role="alert" *ngIf="!username.valid">Invalid username</div>
    <div class="form-group">
      <label for="email">Email: </label>
      <input type="text" class="form-control"
             pattern="[a-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,4}$"
             id="email"
             [(ngModel)]="user.email" name="email" required
             #email="ngModel">
    </div>
    <div class="alert alert-danger" role="alert" *ngIf="!email.valid">Invalid email address</div>
  </div>
  <div class="form-group">
    <label for="password">Password: </label>
    <input type="password" class="form-control"
           id="password"
           [(ngModel)]="user.password" name="password" required>
  </div>
  <div class="radio" *ngFor="let g of genders">
    <label>
      <input type="radio" [(ngModel)] = "user.gender" name="gender" [value]="g"> {{g}}
    </label>
  </div>
  <button type="submit" class="btn btn-primary" [disabled]="!f.valid">Submit</button>
</form>


So here is the output:


This whole code is available in the github. check it out here 
#happyCoding


1 comment: