Template Form Validation in Angular

Form validation is an important part of making sure that what users type into a website is correct. In Angular, there are two ways to do this: Form Validation and Reactive Form Validation (Read my article about it here). This article focuses on Template Form Validation.

Template-driven forms in Angular let you create forms with validation easily. This article gives you a complete guide to using template forms for validation in Angular. It covers everything from making simple forms to adding your own rules for what's allowed. Knowing how to use the built-in validation tools and following some tips can help you make forms that work well.

Understanding Template Forms in Angular

Template-driven forms in Angular make it easy to create forms. They use directives and template syntax in the HTML file. Unlike reactive forms, which use TypeScript code, template-driven forms use directives like ngModel to connect form controls with properties in the component class.

Advantages of Template Forms over Reactive-driven Forms

  • Ease of Use: Template-driven forms are easier to set up and require less boilerplate code compared to reactive-driven forms, making them ideal for simple forms or scenarios where extensive form logic is not necessary.

  • Quick Prototyping: Template-driven forms allow for rapid prototyping and development, as developers can define form structure and validation rules directly in the template without the need for additional TypeScript code.

  • Declarative Approach: With template-driven forms, developers can declare form controls and their validation rules directly within the HTML template, resulting in a more declarative and intuitive development experience.

Overview of FormsModule

In Angular, the FormsModule is a built-in tool that helps with template-based forms. It includes handy commands like ngForm, ngModel, and ngModelGroup, which are important for making and validating forms made with templates.

With ngForm, you can make and handle whole forms. ngModel lets you connect form controls and component properties easily. And ngModelGroup helps group form controls for simpler managing and validation.

Setting Up the Development Environment

To begin a new Angular project, type this command in your terminal:

ng new <filename>

Go to the newly made Angular folder:

cd <filename>

Open the project in Visual Studio Code:

code .

In the app.component.html file, delete the default content, keeping only the router element.

For styling, we'll use Bootstrap. Install Bootstrap by running:

npm i bootstrap@5.3.3

Add this <link> in the <head> section of your HTML file to link to Bootstrap’s CSS file:

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/{version}/css/bootstrap.min.css">

You can find the simple HTML template we'll use in this guide here. Below is a preview of how the template will look, displaying the basic form structure.

Creating a Basic Template Form

To make a simple form in Angular, first, add FormsModule and CommonModule to your Angular module. This helps you use form features and *ngIf in your app.

import { FormsModule, NgForm } from '@angular/forms';
import { CommonModule } from '@angular/common';

@Component({
  other properties
  imports: [RouterOutlet, FormsModule, CommonModule],
})

In your AppComponent class, make a property called userObject to hold user info. It has firstName and lastName set to empty strings.

export class AppComponent {
  userObject: any = {
    firstName: '',
    lastName: '',
  }

  isFormSubmitted: boolean = false;
}

Add a method called onSubmit(). It runs when the form is submitted. It takes a form parameter of type NgForm, a reference to the form object. Inside the method, set isFormSubmitted to true to show the form is submitted.

export class AppComponent {
  // userObject and isFormSubmitted properties

  onSubmit(form: NgForm) {
    this.isFormSubmitted = true;
  }
}

Binding form controls to component properties

In Angular, you can create a reference to a form by adding #userform to the form element. This reference lets you work with the form in your component. When you use "ngForm", it tells Angular that this reference is for handling form actions.

<form class="row g-3 needs-validation" novalidate #userform="ngForm">
  <!-- Other HTML content -->
</form>

To connect an input field to a property in your component, like firstName, you can use [(ngModel)]. This sets up a two-way connection between the input and the firstName property in your AppComponent. The name="firstName" attribute gives the input a name, which is handy for form submissions.

<div class="col-md-6">
  <label class="form-label">First name</label>
  <input type="text" #firstName="ngModel" [(ngModel)]="userObject.firstName" name="firstName" class="form-control" required>
  <div class="text-danger">
    This is required
  </div>
</div>

By adding attributes like required directly in the HTML, you can set up validation rules. For example, required makes sure that the input field must be filled out before the form can be submitted.

To include additional checks in your code, you can simply add more attributes to the syntax. For example:

<label class="form-label">Last name</label>
<input type="text" #lastName='ngModel' [(ngModel)]="userObject.lastName" name="lastName" class="form-control"
minlength="5" required>
<div class="text-danger">
    <span>This is required</span>
    <span>Five characters needed</span>      
</div>

Here, we've added both the minlength and required attributes. The minlength attribute specifies that the input field must contain 5 or more characters.

Dynamically displaying validation errors

We can dynamically display these validations only when it is invalid or have been interacted with, either through touch or submission.

With the *ngIf directive, we decide whether to show the <div> based on a certain condition. This condition checks if the first name input is invalid (firstName.invalid) and if it has been touched (firstName.touched) or interacted with (firstName.dirty). If any of these is true, or if the form has been submitted, then the <div> will be displayed.

We also use the *ngIf directive to decide whether to show the <span> part. This happens only if there's a "required" error in the firstName.errors section.

<div class="col-md-6">
  <label class="form-label">First name</label>
  <input type="text" #firstName="ngModel" [(ngModel)]="userObject.firstName" name="firstName" class="form-control"
    required>
  <div class="text-danger" *ngIf="firstName.invalid && (firstName.touched || firstName.dirty) || isFormSubmitted">
    <span *ngIf="firstName.errors?.['required']">This is required</span>
  </div>
</div>

An image of the app showing a validation error when the input is empty.

Similarly, we can show different error messages based on conditions. For instance, if the input is not long enough or left empty, we can display a message saying "Five or more characters needed" or "This is required" respectively. There are various types of errors we can check for other than the ones listed above, like ensuring the email follows a specific pattern.

<div class="col-md-6">
    <label class="form-label">Last name</label>
    <input type="text" #lastName='ngModel' [(ngModel)]="userObject.lastName" name="lastName" class="form-control"
        minlength="5" required>
    <div class="text-danger" *ngIf="lastName.invalid && (lastName.touched || lastName.dirty) || isFormSubmitted">
        <span *ngIf="lastName.errors?.['required']">This is required</span>
        <span *ngIf="lastName.errors?.['minlength']">Five characters needed</span>
    </div>
</div>

Preview of the app dynamically showing the errors when the input box has been interacted on.

Finally, implement the form submission logic by attaching a click event to the submit button. Call the onSubmit() defined in the AppComponent to handle the form submission. Pass the form reference (userform) to this function to access form values and perform additional validation or processing.

<button class="btn btn-primary" type="button" (click)="onSubmit(userform)">Submit form</button>

If the Submit button is clicked and the form contains invalid inputs, appropriate error messages will be displayed.

Below is the preview of an image that shows the various error messages when the Submit button is clicked without giving it a valid input.

Conclusion

By following these steps, you can implement Template Form validation in Angular templates using HTML attributes and Angular directives. This ensures that user input meets specified criteria before submission, enhancing the overall reliability and user experience of your web application.

Additional Resources

Angular template form

0
Subscribe to my newsletter

Read articles from Sabastine Ugochukwu directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Sabastine Ugochukwu
Sabastine Ugochukwu