Template-driven VS Reactive forms in Angular


Difficulty

Building forms in Angular presents two distinct approaches: template-driven forms vs reactive forms. Choosing the right method depends on your project’s complexity, your team’s comfort level, and the desired level of control over form behavior. This article delves into the strengths and weaknesses of both approaches, equipping you to make an informed decision.

Template-driven forms: Simplicity at the Forefront

We can think this first type of form as a simple way to make forms for those that have not much time. We’ll use it for simple forms, how can be a sign-in one.

Template-driven forms.

Template-driven forms prioritize ease of use and intuitive syntax. They leverage directives embedded within your HTML templates to handle data binding, validation, and form submission.

Key elements:

  • ngModel directive: Binds form elements to data properties in your component class.
  • Validation directives: Add validation rules directly within your HTML form.
  • Form controls: Represent individual form elements and track their state.

Strengths:

  • Quick and easy setup: Ideal for simple forms with basic validation needs.
  • Declarative style: Define form logic directly in your templates, improving readability.
  • Familiar for HTML/JavaScript developers: Requires minimal knowledge of Angular-specific concepts.

Weaknesses:

  • Limited control: Lacks the flexibility and fine-grained control offered by reactive forms.
  • Testing complexity: Testing can be challenging due to reliance on directives and DOM manipulation.
  • Scalability concerns: Becomes cumbersome for complex forms with intricate validation and logic.

form-template-driven.component.ts 💾

import {Component} from '@angular/core';
import {NgForm} from "@angular/forms";

@Component({
  selector: 'app-form-template-driven',
  templateUrl: './form-template-driven.component.html',
  styleUrls: ['./form-template-driven.component.scss']
})
export class FormTemplateDrivenComponent {

  public username: string;
  public password: string;

  constructor() { }

  public handleSubmit(f: NgForm): void {
    console.log('NgForm: ', f);
    if (f.invalid) {
      return;
    }
    console.log(this.username + ' ' + this.password);
  }
}

form-template-driven.component.html 💾

<form #f="ngForm" (ngSubmit)="handleSubmit(f)">
  <div class="form-group">

    <!-- username field -->
    <label for="username">Username: </label>
    <input #usr="ngModel" id="username" name="username"
         [(ngModel)]="username" class="form-control" required minlength="3">
    <div *ngIf="usr.touched">
      <small *ngIf="usr.hasError('required')" class="text-danger">
        Required field
      </small>
      <small *ngIf="usr.hasError('minlength')" class="text-danger">
        At least 3 characters
      </small>
    </div>

    <!-- password field -->
    <label for="password">Password: </label>
    <input #pwd="ngModel" type="password" id="password" name="password"
         [(ngModel)]="password" class="form-control" required minlength="3">

    <!-- submit button -->
    <button type="submit" class="btn btn-primary" [disabled]="f.invalid">SEND</button>
  </div>
</form>

Reactive forms: power and control take center stage

We can think this second type of form as a complete and dinamic way to make forms with every type of custom validation and with much more control from Component. We’ll use it for complex forms, how can be a registration one.

Reactive forms.

Reactive forms prioritize granular control and reactivity. They utilize Observables and streams to manage form data and validation, offering a more programmatic and reactive approach.

Key elements:

  • FormGroup and FormControl classes: Represent form groups and individual controls, respectively.
  • Form builder: Simplifies the creation of complex form structures.
  • Validators: Enforce validation rules programmatically within your component class.

Strengths:

  • High flexibility: Enables custom validation, asynchronous validation, and dynamic form manipulation.
  • Improved testability: Easier to unit test due to clear separation of concerns and dependency injection.
  • Scalability: Well-suited for complex forms with intricate validation and conditional logic.

Weaknesses:

  • Steeper learning curve: Requires a deeper understanding of RxJS and reactive programming concepts.
  • More verbose code: Can lead to longer code compared to template-driven forms for simple scenarios.
  • Potential for over-engineering: Might be overkill for basic forms.

form-reactive-driven.component.ts 💾

import { Component, OnInit } from '@angular/core';
import {AbstractControl, FormControl, FormGroup, Validators} from '@angular/forms';
import {rangeValidator} from "../../validators/range.validator";

@Component({
  selector: 'app-form-reactive-driven',
  templateUrl: './form-reactive-driven.component.html',
  styleUrls: ['./form-reactive-driven.component.scss']
})
export class FormReactiveDrivenComponent implements OnInit {
  public formGruppo: FormGroup;

  constructor() {
    this.formGruppo = new FormGroup({
      username: new FormControl('', [
        Validators.required,
        Validators.minLength(3)
      ]),
      numberInRange: new FormControl('', [
        Validators.required,
        rangeValidator(2, 10)
      ]),
    });
  }

  ngOnInit() {
  }

  get username(): AbstractControl {
    return this.formGruppo.get('username');
  }

  get numberInRange(): AbstractControl {
    return this.formGruppo.get('numberInRange');
  }

  public handle(): void {
    console.log('FormGroup: ', this.formGruppo);
    if (this.formGruppo.invalid) {
      return;
    }
    console.log(this.username);
  }
}

form-reactive-driven.component.html 💾

<form [formGroup]="formGruppo" (ngSubmit)="handle()">
  <div class="form-group">
    <label for="username">Username:</label>
    <input id="username" name="username" formControlName="username" class="form-control">
    <div *ngIf="username.dirty">
      <small *ngIf="username.hasError('required')">Required field</small>
      <small *ngIf="username.hasError('minlength')">At least 3 characters</small>
    </div>
    <br>
    <label for="numberInRange">numberInRange:</label>
    <input id="numberInRange" name="numberInRange" formControlName="numberInRange"
           class="form-control" type="number">
    <div *ngIf="numberInRange.dirty">
      <small *ngIf="numberInRange.hasError('range')">Not valid range</small>
    </div>
    <br>

    <button class="btn btn-primary" type="submit">SEND</button>
  </div>
</form>

Considerations When Choosing

  • Form complexity: For simple forms with basic validation, template-driven forms offer a quicker setup. For complex forms with intricate logic and validation, reactive forms provide more control and scalability.
  • Team expertise: If your team is familiar with directives and traditional form handling, template-driven forms might be easier to adopt. If your team has experience with RxJS and reactive programming, reactive forms might be a better fit.
  • Desired level of control: If you need fine-grained control over form behavior and validation, reactive forms offer more flexibility. If basic control suffices, template-driven forms might be sufficient.

Conclusions on Template-driven VS Reactive forms

Both approaches have their place in the Angular ecosystem. Some developers even adopt a hybrid approach, using template-driven forms for simple sections and reactive forms for complex areas within the same application.

Remember: The choice ultimately depends on your specific project requirements and team preferences. Experiment with both approaches to find the best fit for your needs.

Additional Tips:

  • Leverage the Angular documentation and community resources for comprehensive guidance and code examples.
  • Consider using form libraries like ngx-form or ngx-reactive-forms for additional features and convenience.
  • Test your forms thoroughly, regardless of the chosen approach, to ensure a seamless user experience.

By understanding the strengths and weaknesses of each approach, you can make an informed decision that empowers you to build efficient and robust forms in your Angular applications.

0
Be the first one to like this.
Please wait...

Leave a Reply

Thanks for choosing to leave a comment.
Please keep in mind that all comments are moderated according to our comment policy, and your email address will NOT be published.
Please do NOT use keywords in the name field. Let's have a personal and meaningful conversation.