Skip to content
Menu
Rohit Naik Kundaikar
  • Home
  • Contact
Rohit Naik Kundaikar

Angular Forms: CoversTemplate-Driven Forms and Model-Driven Forms also called as Reactive Form

Posted on October 21, 2020December 10, 2020 by Rohit Naik Kundaikar
Angular Reactive Form / Model Driven Form

Project Setup

In this example, you will see how to create forms in Angular using a Reactive and Template driven approach.

In our demonstration, we will create two forms one using the Reactive approach and the other with a template-driven approach.

Create project and add components that we would need.

ng new angularForm
ng g c modelDrivenForm
ng g c templateDrivenForm

Reactive Form

Reactive forms or Model-driven forms provide a model-driven approach for handling form inputs whose values keep changing over time. 

Let’s create a complex form that takes in user details like its name as Key, address as Object, and languages as Array.

 {
    "firstName": "",
    "lastName": "",
    "address": {
      "landMark": "",
      "state": "",
      "city": "",
      "pincode": ""
     },
    "langKnown": [""]
  }

Firstly import reactive forms module from @angular/forms in app.model.ts. It would export all infrastructure and directives required for handling reactive forms.

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

There are three fundamental building blocks of Angular Forms i.e FormGroup, FormControl, and FormArray. Let’s go over it with examples for better understanding.

FormGroup is used to aggregate values of child FormControl into one object, with each control name as the key of the formGroup object.

Using formGroup also gives an advantage while validating a form, if any key is not valid in the form then it makes the entire form as invalid.

userDetails = this.fb.group({ firstName : [''] })

FormControl is used to track values and validate the form object keys individually which is done by binding formControlName.

<form [formGroup]="user" (ngSubmit)="onSubmit()">
    <input type="text" formControlName="firstName" />
</form>

FormArray is used to aggregate values of each FormControl child into an array.

user = this.fb.group({ langKnown: this.fb.array([this.fb.control('')]) })
<form [formGroup]="user" (ngSubmit)="onSubmit()">
    <div formArrayName="langKnown">
        <div *ngFor="let lang of langKnown.controls; let i=index">
            <input type="text" [formControlName]="i" />
        </div>
    </div>
</form>

The objective of the form is to capture below details

{
    "firstName": "",
    "lastName": "",
    "address": {
      "landMark": "",
      "state": "",
      "city": "",
      "pincode": ""
     },
    "langKnown": [""]
  }

Below is complete example of Reactive Form it implements all the topics that we covered in above section.

import { Component, OnInit } from '@angular/core';
import { FormBuilder, Validators, FormArray } from '@angular/forms';

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

  constructor(private formBuilder: FormBuilder) { }

  ngOnInit(): void { }

  userDetails = this.formBuilder.group({
    firstName: ['', Validators.required],
    lastName: [''],
    address: this.formBuilder.group({
      landMark: [''],
      state: [''],
      city: [''],
      pincode: ['']
    }),
    languagesKnown: this.formBuilder.array([
      this.formBuilder.control('')
    ])
  });
  get languagesKnown() {
    return this.userDetails.get('languagesKnown') as FormArray;
  }
  updateValues() {
    this.userDetails.patchValue({
      firstName: 'Rohit',
      address: {
        landMark: 'Near my house'
      }
    })
  }
  addLang() {
    this.languagesKnown.push(this.formBuilder.control(''));
  }
  onSubmit() {
    console.log(this.userDetails.value);
  }
}
<div class="container">
    <br>
    <form [formGroup]="userDetails" (ngSubmit)="onSubmit()">
        <div class="well">
            <div class="form-group">
                <label for="firstName"> First Name </label>
                <input id="firstName" type="text" class="form-control" formControlName="firstName" />
            </div>
            <div class="form-group">
                <label for="firstName"> Last Name </label>
                <input id="firstName" type="text" class="form-control" formControlName="lastName" />
            </div>
            <div class="form-group" formGroupName="address">
                <label> Address</label>
            </div>
            <div class="form-group" formGroupName="address">
                <label> Land Mark</label>
                <input type="text" class="form-control" formControlName="landMark" />
            </div>
            <div class="form-group" formGroupName="address">
                <label> City</label>
                <input type="text" class="form-control" formControlName="city" />
            </div>
            <div class="form-group" formGroupName="address">
                <label> State</label>
                <input type="text" class="form-control" formControlName="state" />
            </div>
            <div class="form-group" formGroupName="address">
                <label> Pincode</label>
                <input type="text" class="form-control" formControlName="pincode" />
            </div>
            <div formArrayName="languagesKnown">
                <div class="form-group" *ngFor="let lang of languagesKnown.controls; let i=index">
                    <label> Language</label>
                    <input type="text" class="form-control" [formControlName]="i" />
                </div>
                <div class="form-group">
                    <button (click)="addLang()" class="btn btn-default">Add More Languges</button>
                </div>
            </div>
            <div class="form-group" formGroupName="address">
                <button type="submit">Submit</button>
            </div>
        </div>
    </form>
    {{userDetails.value | json}}
</div>

Template Driven Form

Template-driven forms use two-way data binding to update data in the model and in the template. It is quite simple compared to the model-driven approach.

Let’s create a simple form that captures userName, password, and userTypeas shown below.

{ "userName": "", "password": "", "userType": "" }

Create a Login entity class with all the key that it accepts as shown below.

export class Login {
    constructor(
        public userName : string,
        public password : string,
        public userType : string
    ){}
}

Then create an object of this class in the model and assign default values if any.

  model = new User("","","admin");

Below is a brief explanation of directives and events used in the template form.

ngForm : The ngForm directive creates a top-level FormGroup instance and binds it to a <form> element to track aggregated form value and validation status

ngSubmit: The ngSubmit event handles form submission

<form #login="ngForm" (ngSubmit)="onSubmit()">

[(ngModel)] : The [(ngModel)] is used to create two-way data binding for reading and writing input-control values.

When using [(ngModel)] on an element, you need to define a name attribute for that element.

Its a mandate since angular uses the assigned name to register the element with the NgForm directive attached to the parent <form> element.

Below is complete example of template driven approach that discussed above.

<div class="container">
    <br>
    <div class="panel panel-default">
        <div class="panel-heading">Template Driven Form</div>
        <div class="panel-body">
            <form #login="ngForm" (ngSubmit)="onSubmit()">
                <div class="form-group">
                    <label for="firstName"> User Name </label>
                    <input type="text" class="form-control"
                    [(ngModel)]="model.userName"
                    name="userName"
                    id="userName"
                    #userName="ngModel" />
                </div>
                <div class="form-group">
                    <label for="password"> Password </label>
                    <input type="password" class="form-control" 
                    [(ngModel)]="model.password"
                    name="password"
                    id="password"
                    #password="ngModel" />
                </div>
                <div class="form-group">
                    <label for="userType"> User Type </label>
                    <select class="form-control" id="userType" required 
                        [(ngModel)]="model.userType"
                        name="userType"
                        #userType="ngModel">
                        <option value="admin">Admin</option>
                        <option value="user">User</option>
                    </select>
                </div>
                <div class="form-group">
                    <button type="submit"> Submit </button>
                </div>
            </form>
        </div>
    </div>
    {{model | json}}
</div>

Complete source code for Angular Forms example: https://github.com/thatsrohitnaik/Angular-Forms

Happy coding !!

Angular, Forms

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recent Posts

  • Typescript Guide – Part 1
  • Vite Micro Frontend
  • React Best Practice: Part 2
  • React Best Practices: Part 1
  • Redux Toolkit

Recent Comments

    Archives

    • August 2024
    • January 2024
    • September 2021
    • July 2021
    • June 2021
    • May 2021
    • April 2021
    • December 2020
    • November 2020
    • October 2020
    • September 2020

    Categories

    • Angular
    • API
    • Best Practice
    • Compiler
    • Context
    • DevOps
    • Docker
    • FAANG
    • Forms
    • GraphQL
    • Java
    • Javascript
    • Machine Learning
    • MobX
    • Python
    • ReactJS
    • Redux Toolkit
    • Spring Boot
    • Typescript
    • Uncategorized
    • Vite
    • Webpack
    ©2025 Rohit Naik Kundaikar | Powered by WordPress & Superb Themes