Forms – Angular

Angular 17 provides powerful form-handling capabilities through Reactive Forms and Template-driven Forms. These two approaches offer different ways to build forms, depending on the complexity and requirements of the form.

1. Reactive Forms

Reactive forms are more explicit and synchronous; they allow for better control, validation, and state management.

Example: Creating a Reactive Form

  1. Step 1: Import ReactiveFormsModule in your module
    In your app module (app.module.ts), import ReactiveFormsModule.
   import { NgModule } from '@angular/core';
   import { BrowserModule } from '@angular/platform-browser';
   import { ReactiveFormsModule } from '@angular/forms'; // <-- Import this module

   import { AppComponent } from './app.component';

   @NgModule({
     declarations: [AppComponent],
     imports: [BrowserModule, ReactiveFormsModule], // <-- Add it here
     providers: [],
     bootstrap: [AppComponent],
   })
   export class AppModule {}
  1. Step 2: Create a Form in a Component
    In your component, you’ll define a form using FormBuilder, FormGroup, and FormControl.
   import { Component } from '@angular/core';
   import { FormBuilder, FormGroup, Validators } from '@angular/forms';

   @Component({
     selector: 'app-reactive-form',
     template: `
       <form [formGroup]="userForm" (ngSubmit)="onSubmit()">
         <label for="name">Name:</label>
         <input id="name" formControlName="name">
         <div *ngIf="userForm.get('name')?.invalid && userForm.get('name')?.touched">
           Name is required.
         </div>

         <label for="email">Email:</label>
         <input id="email" formControlName="email">
         <div *ngIf="userForm.get('email')?.invalid && userForm.get('email')?.touched">
           Please enter a valid email.
         </div>

         <button type="submit" [disabled]="userForm.invalid">Submit</button>
       </form>

       <pre>{{ userForm.value | json }}</pre>
     `
   })
   export class ReactiveFormComponent {
     userForm: FormGroup;

     constructor(private fb: FormBuilder) {
       this.userForm = this.fb.group({
         name: ['', Validators.required],
         email: ['', [Validators.required, Validators.email]],
       });
     }

     onSubmit() {
       if (this.userForm.valid) {
         console.log('Form Submitted', this.userForm.value);
       }
     }
   }

Explanation:

  • FormGroup: Represents the form as a whole.
  • FormControl: Represents individual form controls (e.g., input fields).
  • FormBuilder: A helper service to build form groups and form controls.
  • Validators are applied to form controls using the Validators class.
  1. Step 3: Using the Form in HTML
    In the template, you bind the form to the component using formGroup, and each control uses formControlName.

2. Template-Driven Forms

Template-driven forms are simpler to use, especially for small forms. Angular automatically tracks form states and values based on the DOM structure.

Example: Creating a Template-Driven Form

  1. Step 1: Import FormsModule in your module
    In your app module (app.module.ts), import FormsModule.
   import { NgModule } from '@angular/core';
   import { BrowserModule } from '@angular/platform-browser';
   import { FormsModule } from '@angular/forms'; // <-- Import this module

   import { AppComponent } from './app.component';

   @NgModule({
     declarations: [AppComponent],
     imports: [BrowserModule, FormsModule], // <-- Add it here
     providers: [],
     bootstrap: [AppComponent],
   })
   export class AppModule {}
  1. Step 2: Create a Form in a Component Template
    In the template-driven approach, you define the form directly in the HTML template.
   import { Component } from '@angular/core';

   @Component({
     selector: 'app-template-form',
     template: `
       <form #userForm="ngForm" (ngSubmit)="onSubmit(userForm)">
         <label for="name">Name:</label>
         <input id="name" name="name" ngModel required>
         <div *ngIf="userForm.submitted && userForm.form.controls.name?.invalid">
           Name is required.
         </div>

         <label for="email">Email:</label>
         <input id="email" name="email" ngModel required email>
         <div *ngIf="userForm.submitted && userForm.form.controls.email?.invalid">
           Please enter a valid email.
         </div>

         <button type="submit" [disabled]="userForm.invalid">Submit</button>
       </form>

       <pre>{{ userForm.value | json }}</pre>
     `
   })
   export class TemplateFormComponent {
     onSubmit(form: any) {
       if (form.valid) {
         console.log('Form Submitted', form.value);
       }
     }
   }

Explanation:

  • Angular automatically registers form controls using the ngModel directive.
  • Form validation is done in the template using HTML attributes like required, email, etc.
  • #userForm="ngForm" creates a reference to the form in the template, and ngForm tracks the form state.
  1. Step 3: Using the Form in HTML
    Use the ngModel directive to bind the form controls to component data and track validation states.

3. Form Validation

Both reactive and template-driven forms support form validation. Validators are applied either declaratively in the template or imperatively in the component code.

Reactive Form Validation Example:

this.userForm = this.fb.group({
  name: ['', [Validators.required, Validators.minLength(4)]],
  email: ['', [Validators.required, Validators.email]],
  password: ['', [Validators.required, Validators.pattern('(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{8,}')]],
});

Template-Driven Form Validation Example:

<input name="password" ngModel required minlength="8" pattern="(?=.*\d)(?=.*[a-z])(?=.*[A-Z]).{8,}">

4. Form Array

In Reactive Forms, FormArray is used when you want to manage an array of form controls. It’s helpful when you need to dynamically add or remove form elements.

Example: Dynamic Form using FormArray

this.userForm = this.fb.group({
  name: ['', Validators.required],
  emails: this.fb.array([]),
});

get emails() {
  return this.userForm.get('emails') as FormArray;
}

addEmail() {
  this.emails.push(this.fb.control(''));
}

removeEmail(index: number) {
  this.emails.removeAt(index);
}

Conclusion

Angular 17 continues to enhance form handling with both reactive and template-driven approaches. Here’s a summary:

  • Reactive Forms: More flexible and scalable, better for complex forms.
  • Template-driven Forms: Simpler and easier to use for small or medium-sized forms.
  • Both approaches support validation and can be used based on the form’s complexity and requirements.
Tags: No tags

Add a Comment

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