Angular Forms

ANGULAR FORMS

User INPUT data are collected using Angular forms. 

There are two approaches by which we can create forms in angular.

  1. Template Driven Forms
  2. Model Driven Forms

1. TEMPLATE DRIVEN FORMS

First, we build a simple Contact form. The ngForm directive will convert it to the Template-driven form and create the top-level FormGroup control.\

Next, we use the ngModel directive to create the FormControl instance for each of the HTML form elements. 



<form #contactForm="ngForm" (ngSubmit)="onSubmit(contactForm)">
  <h1 class="text-center"> <strong> ANGULAR TEMPLATE DRIVEN FORM DEMO</strong></h1>
  <br>
  <div class="container">
    <div class="row">
      <div class="col-md-6">
        <div class="mb-1">
          <label class="form-label" for="firstname">First Name</label>
          <div class="input-group">
            <input type="text" class="form-control" name="firstname" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="lastname">Last Name</label>
          <div class="input-group">
            <input type="text"  class="form-control" name="lastname" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="email">Email </label>
          <div class="input-group">
            <input type="text" class="form-control" id="email" name="email" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="gender">Geneder</label> 
          <div class="input-group">
            <input type="radio" value="male" name="gender" ngModel> Male
            <input type="radio" value="female" name="gender" ngModel> Female
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="isMarried">Married</label> 
          <div class="input-group">
            <input type="checkbox" name="isMarried" ngModel>
          </div>
        </div>
        <div class="mb-1">
          <label class="form-label" for="country">Country</label>
         
          <div class="input-group">
            <select name="country"  class="form-control" ngModel>
              <option [ngValue]="c.id" *ngFor="let c of countryList">
                {{c.name}}
              </option>
            </select>
          </div>
        </div>
        <div ngModelGroup="address">
          <div class="mb-1">
            <label class="form-label" for="city">City</label> 
            <div class="input-group">
              <input type="text" class="form-control" name="city" ngModel>
            </div>
          </div>
          <div class="mb-1">
            <label class="form-label" for="street">Street</label> 
            <div class="input-group">
              <input type="text" class="form-control" name="street" ngModel>
            </div>
          </div>
          <div class="mb-1">
            <label class="form-label" for="pincode">Pin Code</label> 
            <div class="input-group">
              <input class="form-label" class="form-control" type="text" name="pincode" ngModel>
            </div>
          </div> 
          <div class="mb-1">
            <div class="input-group">
              <button class="btn btn-primary" type="submit">Submit</button>
            </div>
          </div>
         
      </div>
      </div>
      <div class="col-md-6">
        <pre>Value : {{contactForm.value | json }} </pre>
        <pre>Valid : {{contactForm.valid}} </pre>
        <pre>Touched : {{contactForm.touched  }} </pre>
        <pre>Submitted : {{contactForm.submitted  }} </pre>
      </div>  
    </div> 
  </div> 
  </form>

Next, we will submit the form data to the component class. 

import { Component, OnInit } from '@angular/core';
export class country {
  id:string;
  name:string;
 
  constructor(id:string, name:string) {
    this.id=id;
    this.name=name;
  }
}
@Component({
  selector: 'app-templatedrivenform',
  templateUrl: './templatedrivenform.component.html',
  styleUrls: ['./templatedrivenform.component.css']
})
export class TemplatedrivenformComponent implements OnInit {

  constructor() { }

  ngOnInit(): void {
  }
  countryList:country[] = [
    new country("1", "India"),
    new country('2', 'USA'),
    new country('3', 'England')
  ];
  onSubmit(contactForm: { value: any; }) {
    console.log(contactForm.value);
  }

}

OUTPUT

Angular forms

2. MODEL DRIVEN FORMS (REACTIVE FORMS)

In Reactive forms we define the structure of the form in the component class. i.e. We define the form model with Form Groups, Form Control and Form Arrays. And then we define validation rules in the component class. And finally, we bind it to the HTML form in the template.

How to use Reactive Forms

  1. Import ReactiveFormsModule
  2. Defining Form Model in the component
  3. Create the HTML Form uses the Form Model properties.Bind the HTML Form to the Form Model

1. Import ReactiveFormsModule

import { FormsModule, ReactiveFormsModule } from '@angular/forms';

 imports: [
     
     //  Angular Form Modules
    FormsModule,
    ReactiveFormsModule
  ],

2. Defining Form Model in the component

FormGroup Represents a collection of form controls. It can also contain other Form Groups and FormArrays. In fact, an angular form is a FormGroup.

FormControl Encapsulates the state of a single form element in our form. It stores the value and state of the form element and helps us to interact with them using properties & methods.

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { UserService } from '../service/user.service';

@Component({
  selector: 'app-add-user',
  templateUrl: './add-user.component.html',
  styleUrls: ['./add-user.component.css']
})
export class AddUserComponent implements OnInit {

  id: number = 0;
  userform: FormGroup;

  constructor(
    private route: ActivatedRoute,
    private router: Router,
    private fb: FormBuilder,
    private userService: UserService
  ) {
    //**************Create Reactive Form with validation********************* */
    this.userform = this.fb.group({
      name: ['', [Validators.required]],
      mobile: ['', []],
      email: ['', [Validators.required, Validators.email, Validators.pattern('^[a-z0-9._%+-]+@[a-z0-9.-]+\\.[a-z]{2,4}$')]],
      gender: ['', [Validators.required]],
      dob: [null, [Validators.required]],
      id: [0, [Validators.required]],
      isActive: [true],
      rating: [0, []],
      userType: ['', [Validators.required]],
    });

  }

  ngOnInit(): void {
    //**************Get User ID On Edit********************* */
    this.route.params.subscribe(params => {
      this.id = params['id'];
      if (params['id'] != null) {
        this.userform.get('Id')?.setValue(params['id']);
        const data = this.userService.getUsersByID(this.id);
        if (data) {
          this.userform.setValue(data);
        }
      }
    });
  }

  save() {
    if (this.userform.invalid) // true if any form validation fail
      return

    if (this.userform.get('id')?.value === 0) {
      // on Create New User
      this.userService.addUser(this.userform.value);
    } else {
      // on Update User info
      this.userService.updateUser(this.userform.value);
    }

    //Redirecting to user List page after save or update 
    this.router.navigate(['/user']);
  }

}

3. User Form

<div class="container">
  <form [formGroup]="userform" autocomplete="off">
      <div class="mb-1">
          <label for="name" class="form-label">Name</label>
          <div class="input-group has-validation">
              <input type="text" #name [ngClass]="{'form-control': true, 'is-invalid': userform.get('name')?.invalid && 
              (userform.get('name')?.dirty || userform.get('name')?.touched)}" id="name" name="name"
                  formControlName="name" placeholder="Name">
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="mobile" class="form-label">Mobile</label>
          <div class="input-group has-validation">
              <input type="number" maxlength="10" [ngClass]="{'form-control': true, 'is-invalid': userform.get('mobile')?.invalid && 
              (userform.get('mobile')?.dirty || userform.get('mobile')?.touched)}" id="mobile" name="mobile"
                  formControlName="mobile" placeholder="Mobile">
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="rating" class="form-label">Rating</label>
          <div class="input-group has-validation">
            <input type="number" maxlength="10" [ngClass]="{'form-control': true, 'is-invalid': userform.get('rating')?.invalid && 
            (userform.get('rating')?.dirty || userform.get('rating')?.touched)}" id="rating" name="rating"
                formControlName="rating" placeholder="rating"> 
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="email" class="form-label">Email</label>
          <div class="input-group has-validation">
              <input type="email" [ngClass]="{'form-control': true, 'is-invalid': userform.get('email')?.invalid && 
                  (userform.get('email')?.dirty || userform.get('email')?.touched)}" id="email" name="email"
                  formControlName="email" placeholder="xyz@gmail.com">
              <div class="invalid-feedback">
                  {{userform.get('email')?.hasError('required') ? 'This field is required.':'Invalid Email'}}
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="DOB" class="form-label">DOB</label>
          <input type="date" [ngClass]="{'form-control': true, 'is-invalid': userform.get('dob')?.invalid && 
                  (userform.get('dob')?.dirty || userform.get('dob')?.touched)}" id="dob" name="dob"
                  formControlName="dob"> 
      </div>
      <div class="mb-1">
          <label for="email" class="form-label">Gender {{userform.get('gender')?.value}} </label>
          <div class="input-group has-validation">
              <select [ngClass]="{'form-select': true, 'is-invalid': userform.get('gender')?.invalid && 
                  (userform.get('gender')?.dirty || userform.get('gender')?.touched)}"
                  aria-label="Default select example" formControlName="gender">
                  <option value=""> --Select--</option>
                  <option value="Male" selected="userform.get('gender')?.value=='Male'">Male</option>
                  <option value="Female" selected="userform.get('gender')?.value=='Female'">Female</option>
              </select>
              <div class="invalid-feedback">
                  This field is required.
              </div>
          </div>
      </div>
      <div class="mb-1">
          <label for="name" class="form-label">User Type</label>
          <div class="input-group has-validation">
              <div class="form-check form-check-inline">
                  <input class="form-check-input" formControlName="userType" type="radio" id="User" value="User">
                  <label class="form-check-label" for="User">User</label>
              </div>
              <div class="form-check form-check-inline">
                  <input class="form-check-input" formControlName="userType" type="radio" id="Admin" value="Admin">
                  <label class="form-check-label" for="Admin">Admin</label>
              </div>
          </div>
      </div>
      <div class="mb-1">
          <div class="form-check form-switch">
              <input class="form-check-input" type="checkbox" formControlName="isActive" id="isActive">
              <label class="form-check-label" for="isActive">Is Active</label>
          </div>
      </div>
      <div class="mb-1">
          <div class="btn-group" role="group" aria-label="Basic example">
              <button (click)="save()" [disabled]="userform.invalid" class="btn btn-primary" type="button">
                  {{id==0 || id==null ?'Save':'Update'}}</button>
              <button class="btn btn-secondary" type="button">Reset </button>
          </div>
      </div>

      <div class="mb-1">
          {{userform.value |json}}
      </div>
  </form>
</div>

OUTPUT

Angular forms

DOWNLOAD SOURCE CODE