19 Years of Excellence 99% Hiring Rate

Reactive and Template Driven Forms in Angular with Easy Examples

Forms are an important part of any website or app. They allow us to enter important information like usernames, email addresses, phone numbers, etc. Businesses and organizations always need visitors’ details to convert them into customers. Angular provides two main approaches for handling forms: reactive forms and template-driven forms. Both approaches take input from the users using view and complete the data validation. Later, they update the form from a data model and provide a way to monitor all the changes made by the user.

Angular Js Quizzes

Reactive Forms in Angular

Reactive Forms is an approach where forms are built programmatically in Angular. Unlike the template-driven forms, which work on an HTML template, Reactive Forms are built in the TypeScript code. Reactive Forms give us more control over form validation and data handling.

Key Features of Reactive Approach

  • Programmatic Form Creation: It allows us to have programmatic control over form components. We can define form controls using Form Control, Form Group, and Form Array.
  • Synchronous Updates:  Forms input and validation are updated in real time.
  • Scalability: Best suited for complex forms with many fields or dynamic structures.
  • Advance Validation: support both built-in and custom validators. Custom validation helps us to make a complex validation form.
  • Form Control States:
  • Valid: This means when the user enters the correct details.
  • Invalid: When the user enters the wrong information, and the form throws an error.
  • Touched: Field was interacted with.
  • Dirty: When the user changes the input field value.

Handling Forms with Reactive Approach

Reactive Forms in Angular are a model-driven approach. This approach offers better control over form validation, dynamic changes, and scalability compared to template-driven forms.

Steps to Create a Reactive Form in Angular

1️. Import ReactiveFormsModule

First, import ReactiveFormsModule in your app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { ReactiveFormsModule } from '@angular/forms';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, ReactiveFormsModule], // Add ReactiveFormsModule
  bootstrap: [AppComponent]
})
  
export class AppModule {}

2️. Define the Form in TypeScript

In app.component.ts, create a FormGroup with form controls:

import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  // Create FormGroup
  myForm = new FormGroup({
    name: new FormControl('', [Validators.required, Validators.minLength(3)]), // Name field with validation
    email: new FormControl('', [Validators.required, Validators.email]), // Email field with validation
    password: new FormControl('', [Validators.required, Validators.minLength(6)])
  });

  // Handle Form Submission
  onSubmit() {
    console.log('Form Submitted:', this.myForm.value);
  }
}

3️. Create the Form in HTML

In app.component.html, bind the form to the component using formGroup:

<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <!-- Name Input -->
  <label for="name">Name:</label>
  <input type="text" id="name" formControlName="name" />
  <div *ngIf="myForm.get('name')?.invalid && myForm.get('name')?.touched">
    <small *ngIf="myForm.get('name')?.errors?.required">Name is required.</small>
    <small *ngIf="myForm.get('name')?.errors?.minlength">Must be at least 3 characters.</small>
  </div>

  <!-- Email Input -->
  <label for="email">Email:</label>
  <input type="email" id="email" formControlName="email" />
  <div *ngIf="myForm.get('email')?.invalid && myForm.get('email')?.touched">
    <small *ngIf="myForm.get('email')?.errors?.required">Email is required.</small>
    <small *ngIf="myForm.get('email')?.errors?.email">Invalid email format.</small>
  </div>

  <!-- Password Input -->
  <label for="password">Password:</label>
  <input type="password" id="password" formControlName="password" />
  <div *ngIf="myForm.get('password')?.invalid && myForm.get('password')?.touched">
    <small *ngIf="myForm.get('password')?.errors?.required">Password is required.</small>
    <small *ngIf="myForm.get('password')?.errors?.minlength">Must be at least 6 characters.</small>
  </div>

  <!-- Submit Button -->
  <button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>

Features of Reactive Forms

✔ Better validation handling
✔ Easier to manage complex forms
✔ Supports dynamic form controls
✔ Easier testing

Validators in Reactive Forms (Angular)

Angular Reactive Forms provide built-in validators and allow you to create custom validators for complex validation logic.

1. Built-in Validators

Angular provides several built-in validators under the Validators class.

Common Built-in Validators

ValidatorDescription
Validators.requiredField must not be empty
Validators.minLength(length)Minimum character length
Validators.maxLength(length)Maximum character length
Validators.pattern(regex)Must match a specific pattern
Validators.emailEnsures a valid email format
Validators.min(value)Minimum number allowed
Validators.max(value)Maximum number allowed

Example: Applying Built-in Validators

Modify app.component.ts:

import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  myForm = new FormGroup({
    name: new FormControl('', [Validators.required, Validators.minLength(3)]),
    email: new FormControl('', [Validators.required, Validators.email]),
    password: new FormControl('', [Validators.required, Validators.minLength(6)]),
    age: new FormControl('', [Validators.required, Validators.min(18), Validators.max(60)]),
  });

  onSubmit() {
    console.log('Form Data:', this.myForm.value);
  }
}
Displaying Validation Errors in HTML
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
  <input type="text" formControlName="name" placeholder="Enter Name" />
  <div *ngIf="myForm.get('name')?.invalid && myForm.get('name')?.touched">
    <small *ngIf="myForm.get('name')?.errors?.required">Name is required.</small>
    <small *ngIf="myForm.get('name')?.errors?.minlength">Minimum 3 characters required.</small>
  </div>
   <button type="submit" [disabled]="myForm.invalid">Submit</button>
</form>

2. Custom Validators

If the built-in validators are not enough, you can create your custom validators.

Example: Custom Validator for Strong Password

A strong password must contain at least one uppercase letter, one digit, and one special character.

Step 1: Create a Custom Validator Function

Create a new file password.validator.ts:

import { AbstractControl, ValidationErrors } from '@angular/forms';

export function strongPasswordValidator(control: AbstractControl): ValidationErrors | null {
  const password = control.value;

  if (!password) return null; // If empty, let required validator handle it.
  const strongPasswordRegex = /^(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{6,}$/;
  return strongPasswordRegex.test(password) ? null : { weakPassword: true };
}

Step 2: Apply the Custom Validator

Modify app.component.ts:

import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { strongPasswordValidator } from './password.validator';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  myForm = new FormGroup({
    password: new FormControl('', [Validators.required, strongPasswordValidator]),
  });
}

Step 3: Display Validation Messages in HTML

<input type="password" formControlName="password" placeholder="Enter Password" />
<div *ngIf="myForm.get('password')?.invalid && myForm.get('password')?.touched">
  <small *ngIf="myForm.get('password')?.errors?.required">Password is required.</small>
  <small *ngIf="myForm.get('password')?.errors?.weakPassword">
    Password must have at least 1 uppercase, 1 number, and 1 special character.
  </small>
</div>

3. Async Validators (For API Validation)

If you need to validate a field asynchronously, like checking if an email is already taken, you can use async validators.

Example: Async Validator to Check if Email Exists

Create a new file email.validator.ts:

import { AbstractControl } from '@angular/forms';
import { Observable, of } from 'rxjs';
import { delay, map } from 'rxjs/operators';

// Simulate an API call
const existingEmails = ['test@example.com', 'user@email.com'];

export function emailExistsValidator(control: AbstractControl): Observable<{ emailTaken: true } | null> {
  return of(existingEmails.includes(control.value)).pipe(
    delay(1000), // Simulate network delay
    map(exists => (exists ? { emailTaken: true } : null))
  );
}

Apply it in app.component.ts:

import { Component } from '@angular/core';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { emailExistsValidator } from './email.validator';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  myForm = new FormGroup({
    email: new FormControl('', [Validators.required, Validators.email], [emailExistsValidator]),
  });
}

HTML:

<input type="email" formControlName="email" placeholder="Enter Email" />
<div *ngIf="myForm.get('email')?.invalid && myForm.get('email')?.touched">
  <small *ngIf="myForm.get('email')?.errors?.required">Email is required.</small>
  <small *ngIf="myForm.get('email')?.errors?.email">Invalid email format.</small>
  <small *ngIf="myForm.get('email')?.errors?.emailTaken">Email already exists.</small>
</div>

Summary of Reactive Forms in Angular

Built-in Validators: required, minLength, email, pattern, etc.
Custom Validators: For advanced validation like strong passwords.
Async Validators: For checking API data, like email availability.

Template Driven Forms

Template-driven Forms are used for small or simple forms, while Reactive forms are mostly used for complex forms. Template-driven forms use Two-ways binding to update the date model in the component as changes are made in the Template and vice versa. You can build any kind of form using Template- login form, contact form, and any business form. It uses built-in validators to manage the form input and user validation.

Key features of Template Driven approach

  • Simple and easy to use: Template-driven forms are simple to implement, and most of the logic is handled in an HTML template, which makes the code clean and simple. In template-driven forms, Angular automatically manages form control and validation.
  • Use ng-model for two-way binding: In template-driven form, Angular uses ng-model for two-way binding means data can flow in both directions, from the component to the form and from the form to the component.
  • Automatic form management: In template-driven forms, Angular automatically manages form data like form control, form state, form validation, and form submission.

It used ng-directives for controlling the form.

  • Built-in form validation: Angular has various built-in Validator methods for controlling the form. These validators can be applied using HTML attributes, and Angular automatically checks the input against them. Examples- requires, minLength, maxLength, min, max, disabled, required.
  • Form state Tracking: Angular automatically tracks the state of each form and form control. Like when we make changes in the input field, update, delete, or enter any invalid data so all these actions are tracked by Angular automatically.

Working with Template-Driven Forms in Angular

Template-driven forms in Angular allow you to handle form validation and data binding directly in the template (.html file). The best thing is that you don’t need to write much TypeScript code.


Steps to Create a Template-Driven Form in Angular

1️. Import FormsModule

Before using template-driven forms, import FormsModule in your app.module.ts:

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms'; // Import FormsModule
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, FormsModule], // Add FormsModule here
  bootstrap: [AppComponent]
})

export class AppModule {}

2️. Create the Form in HTML

In your app.component.html, create a simple form using ngModel:

<form #myForm="ngForm" (ngSubmit)="onSubmit()"><br>  <!-- Name Input --><br>  <label for="name">Name:</label><br>  <input type="text" id="name" name="name" [(ngModel)]="user.name" required /><br><br>  <!-- Email Input --><br>  <label for="email">Email:</label><br>  <input type="email" id="email" name="email" [(ngModel)]="user.email" required email /><br><br>  <!-- Submit Button --><br>  <button type="submit" [disabled]="myForm.invalid">Submit</button><br></form>

3️. Handle Form Submission in TypeScript

In app.component.ts, define the user object and onSubmit() method:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent {
  user = { name: '', email: '' }; // Data model

  onSubmit() {
    console.log('Form Submitted!', this.user);
  }
}

Form Validation in Template-Driven Forms

Angular automatically validates form fields using directives like required, email, minlength, etc.

Example of error messages:

<input type="email" name="email" [(ngModel)]="user.email" required email #emailField="ngModel" />
<div *ngIf="emailField.invalid && emailField.touched">
  <small *ngIf="emailField.errors?.required">Email is required.</small>
  <small *ngIf="emailField.errors?.email">Invalid email format.</small>
</div>

Advantages of Template-Driven Forms

✅ Simple and easy to use
✅ Less code in TypeScript, more in HTML
✅ Best for small and simple forms

Disadvantages

Not suitable for complex forms
Difficult to scale and maintain


Conclusion: Reactive vs Template Driven– when to use

Templates driven and reactive forms these both approaches in Angular are very a powerful way to handle user input, but both have their benefits. Reactive forms are mostly used for complex designs, while template-driven forms are used for simple and small forms.

Both approaches are valid, and it’s your choice which one you choose according to your application needs and complexity. For complex forms, Reactive is better, while for simple forms, template driven is good.

Similar Blogs to Read

Related Posts

Talk to Us