Angular Forms – Template Driven and Reactive

Forms are the mainstay of business applications. You use forms to log in, submit a help request, place an order, book a flight, schedule a meeting, and perform countless other data-entry tasks. Improve overall data quality by validating user input for accuracy and completeness.

Code for this example can be downloaded from below links –

There are two types of forms in Angular.

  1. Template Driven Forms
  2. Reactive Forms

Template Driven Forms

In this kind of form, we can write the forms in Angular template syntax with form syntax directives.

Following are the steps to build template driven forms.

  1. Create the component that controls the form.
  2. Create a template with the initial form layout.
  3. Bind data properties to each form control using the two-way data-binding syntax.
  4. Add an attribute to each form-input control.
  5. Add custom CSS to provide visual feedback.
  6. Show and hide validation-error messages.
  7. Handle form submission with ngSubmit.
  8. Disable the form’s Submit button until the form is valid.

Reactive Forms

We have used Reactive Forms to add Todo’s in our example in previous article. Reactive forms is an Angular technique for creating forms in a reactive style. Angular reactive forms facilitate a reactive style of programming that favors explicit management of the data flowing between a non-UI data model (typically retrieved from a server) and a UI-oriented form model that retains the states and values of the HTML controls on the screen. Reactive forms offer the ease of using reactive patterns, testing, and validation.

In continuation with previous post on CRUD operations, we had created a form to add Todo’s into the system. There we used reactive forms as shown below –

todo-add.component.html

<div id="addTodo" *ngIf="displayAddTodo">
  <form [formGroup]="formGroup" novalidate (ngSubmit)="addTodo()">
    <table>
      <tr>
        <td colspan="2">
          <mat-form-field>
            <input formControlName="name" matInput placeholder="Task Name">
          </mat-form-field>
          <mat-error>
            <span *ngIf="!formGroup.get('name').valid && formGroup.get('name').touched">Please enter Task
              name</span>
          </mat-error>
        </td>
      </tr>
      <tr>
        <td colspan="2">
          <mat-form-field>
            <input formControlName="desc" matInput placeholder="Description">
          </mat-form-field>
          <mat-error>
            <span *ngIf="!formGroup.get('desc').valid && formGroup.get('desc').touched">Please enter Description
            </span>
          </mat-error>
        </td>
      </tr>
      <tr>
        <td colspan="2">
          <mat-form-field>
            <mat-label>Status</mat-label>
            <mat-select formControlName="status">
              <mat-option value="Pending">Pending</mat-option>
              <mat-option value="Cancelled">Cancelled</mat-option>
              <mat-option value="Done">Done</mat-option>
            </mat-select>
          </mat-form-field>
          <mat-error>
            <span *ngIf="!formGroup.get('status').valid && formGroup.get('status').touched">Please enter status</span>
          </mat-error>
        </td>
      </tr>

      <tr>
        <td colspan="2" class="content-center">
          <button mat-raised-button color="accent" [disabled]="!formGroup.valid" (onClick)="addTodo($event)">Submit</button>
              
          <p-button class="btnAdd" label="BACK" (onClick)="goBack()"></p-button>

        </td>
      </tr>
      <tr>
        <td></td>
      </tr>
    </table>
  </form>
  <br>

  <!-- <p-button class="btnAdd" label="BACK" routerLink="/home/add-bcd/nar"></p-button> -->
</div>

First, we need to import some of the modules from the @angular/forms.

  1. FormGroup – This groups the form elements and access their values.
  2. FormBuilder – We have used form builder to handle all the validation.
  3. Validators –  Assigns Validation rules to the Form Object. Also, we need have imported ReactiveFormsModule  in  app.module.ts file.

todo-add.component.ts

import { Component, OnInit, Output, EventEmitter, Input } from '@angular/core';
import { FormBuilder, Validators, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { TodoService } from './../../services/todo.service';
import { NotifierService } from 'angular-notifier';

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

  formGroup: FormGroup;

  @Output() valueChange = new EventEmitter();
  displayAddTodo: boolean;

  @Input() todo = { name: '', desc: '', status: '' };

  constructor(private formBuilder: FormBuilder, private router: Router, private todoService: TodoService,
    private notifier: NotifierService) { }

  ngOnInit() {
    this.displayAddTodo = true;
    this.initializeTodoForm();
  }

  addTodo() {
    if (this.formGroup.valid) {
      let todo = this.formGroup.value;
      console.log("Todo data " + todo);
      this.todoService.createTodo(todo).subscribe((data: {}) => {
        //this.router.navigate(['/todo-list']);
        this.notifier.notify("success","Todo added successfully");
      })
    }
  }

  initializeTodoForm() {
    this.formGroup = this.formBuilder.group({
      name: ['', [Validators.required]],
      desc: ['', [Validators.required]],
      status: ['', [Validators.required]]
    });
  }

  goBack(): void {
    this.displayAddTodo = false;
    console.log("Back clicked= " + this.displayAddTodo);
    this.valueChange.emit(this.displayAddTodo);
  }
}

We have used form builder (private formBuilder: FormBuilder) to handle all the validation. So in that constructor, we are creating a form with the validation rules.

formGroup: FormGroup – This object is used to access form elements .

Leave a Comment

Bitnami