Template-driven forms in Angular are a way to create forms using Angular's powerful template syntax. This approach is more declarative and relies heavily on Angular's directives to bind form elements to data models.

Key Concepts

  1. FormsModule: To use template-driven forms, you need to import the FormsModule in your Angular module.
  2. ngModel Directive: This directive binds form inputs to model properties.
  3. Form Validation: Angular provides built-in validators and allows you to create custom validators.
  4. Form Submission: Handling form submission and accessing form data.

Setting Up Template-driven Forms

Step 1: Import FormsModule

First, you need to import the FormsModule in your Angular module.

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

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, FormsModule],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Step 2: Create a Form in the Template

Create a form in your component's template using Angular's template syntax.

<!-- app.component.html -->
<form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" ngModel required>
  </div>
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" ngModel required email>
  </div>
  <button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>

Step 3: Handle Form Submission

In your component class, handle the form submission and access the form data.

// app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  onSubmit(form: any): void {
    console.log('Form Data: ', form.value);
  }
}

Form Validation

Angular provides several built-in validators such as required, minlength, maxlength, email, etc. You can also create custom validators.

Built-in Validators

<!-- app.component.html -->
<form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" ngModel required minlength="3">
    <div *ngIf="userForm.controls.name?.invalid && userForm.controls.name?.touched">
      <small *ngIf="userForm.controls.name?.errors?.required">Name is required.</small>
      <small *ngIf="userForm.controls.name?.errors?.minlength">Name must be at least 3 characters long.</small>
    </div>
  </div>
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" ngModel required email>
    <div *ngIf="userForm.controls.email?.invalid && userForm.controls.email?.touched">
      <small *ngIf="userForm.controls.email?.errors?.required">Email is required.</small>
      <small *ngIf="userForm.controls.email?.errors?.email">Invalid email address.</small>
    </div>
  </div>
  <button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>

Custom Validators

You can create custom validators by defining a function that returns an object if the validation fails or null if it passes.

// app.component.ts
import { Component } from '@angular/core';
import { NgModel } from '@angular/forms';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  onSubmit(form: any): void {
    console.log('Form Data: ', form.value);
  }

  validateName(control: NgModel): { [key: string]: boolean } | null {
    const name = control.value;
    if (name && name.length < 3) {
      return { 'nameInvalid': true };
    }
    return null;
  }
}
<!-- app.component.html -->
<form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)">
  <div>
    <label for="name">Name:</label>
    <input type="text" id="name" name="name" ngModel [ngModelOptions]="{ updateOn: 'blur' }" #name="ngModel" [ngModel]="validateName(name)">
    <div *ngIf="name.invalid && name.touched">
      <small *ngIf="name.errors?.nameInvalid">Name must be at least 3 characters long.</small>
    </div>
  </div>
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" ngModel required email>
    <div *ngIf="userForm.controls.email?.invalid && userForm.controls.email?.touched">
      <small *ngIf="userForm.controls.email?.errors?.required">Email is required.</small>
      <small *ngIf="userForm.controls.email?.errors?.email">Invalid email address.</small>
    </div>
  </div>
  <button type="submit" [disabled]="userForm.invalid">Submit</button>
</form>

Practical Exercise

Exercise 1: Create a Registration Form

Create a registration form with the following fields:

  • Username (required, minimum length 5)
  • Password (required, minimum length 8)
  • Email (required, valid email)

Solution

<!-- registration.component.html -->
<form #registrationForm="ngForm" (ngSubmit)="onSubmit(registrationForm)">
  <div>
    <label for="username">Username:</label>
    <input type="text" id="username" name="username" ngModel required minlength="5">
    <div *ngIf="registrationForm.controls.username?.invalid && registrationForm.controls.username?.touched">
      <small *ngIf="registrationForm.controls.username?.errors?.required">Username is required.</small>
      <small *ngIf="registrationForm.controls.username?.errors?.minlength">Username must be at least 5 characters long.</small>
    </div>
  </div>
  <div>
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" ngModel required minlength="8">
    <div *ngIf="registrationForm.controls.password?.invalid && registrationForm.controls.password?.touched">
      <small *ngIf="registrationForm.controls.password?.errors?.required">Password is required.</small>
      <small *ngIf="registrationForm.controls.password?.errors?.minlength">Password must be at least 8 characters long.</small>
    </div>
  </div>
  <div>
    <label for="email">Email:</label>
    <input type="email" id="email" name="email" ngModel required email>
    <div *ngIf="registrationForm.controls.email?.invalid && registrationForm.controls.email?.touched">
      <small *ngIf="registrationForm.controls.email?.errors?.required">Email is required.</small>
      <small *ngIf="registrationForm.controls.email?.errors?.email">Invalid email address.</small>
    </div>
  </div>
  <button type="submit" [disabled]="registrationForm.invalid">Register</button>
</form>
// registration.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-registration',
  templateUrl: './registration.component.html',
  styleUrls: ['./registration.component.css']
})
export class RegistrationComponent {
  onSubmit(form: any): void {
    console.log('Registration Form Data: ', form.value);
  }
}

Summary

In this section, you learned about template-driven forms in Angular. You covered:

  • Setting up template-driven forms by importing FormsModule.
  • Using the ngModel directive to bind form inputs to model properties.
  • Implementing form validation using built-in and custom validators.
  • Handling form submission and accessing form data.

Next, you will learn about reactive forms, which provide a more programmatic approach to form handling in Angular.

© Copyright 2024. All rights reserved