Template-driven Forms in Angular

Learn via video courses
Topics Covered

Angular's template-driven forms, one of two form-building methods, simplify complex form management using Angular's two-way data binding. Unlike model-driven forms, they rely on HTML directives for form control, making them asynchronous and view-driven. Ideal for enterprise applications, they efficiently handle complex, multi-step forms with intricate validation, reducing the time and potential errors of manual form creation. This article delves into using template-driven forms for practical scenarios like hospital or school admissions, emphasizing the need for importing FormModule in Angular's AppModule.

Prerequisites

  • TypeScript and HTML programming
  • Principles of Angular application architecture
  • Fundamentals of Angular template syntax
  • Form-design concepts

Form Setup

We make a basic form component with a basic form template and a simple component, just like the user profile form component we started with in this section:

Directives

The directives we need to construct template-driven forms in angular are in the FormsModule, so import it and add it as an import to our NgModule.

One of the directives retrieved from the FormsModule is known as NgForm. This directive's selector matches the <form> tag.

This ngForm object is hidden, but we can disclose it by attaching a local template reference variable to the form element, as shown:

We can now use the variable userForm in our template to point to our ngForm directive object.

Two-Way Data Binding

The form module in Angular implements a directive with the [(ngModel)] selector, which allows us to quickly perform data binding in two directions: from the view to the model and from the model to the view.

Terminology

[(...)] - Used for two-way binding Also known as banana-in-the-box as it looks like the same.

Let's take a look at the following simple component:

Here, we've connected [(ngModel)] with the name, so whatever changes we will do it will be stored in the name variable.

We already know that the (eventName) syntax is used to connect to events generated by a certain component.

On the other side, we use the [propertyName]= "foo" syntax to create one-way data binding by setting the value of the property.

The [(ngModel)] syntax combines both to provide bidirectional data binding.

Domain Model

In Angular, we normally won't data bind to a simple string or object on our component but to a domain model specified via a class or interface, such as User for our User Profile form.

Now, create an object for the interface User:

Now let's bind all our input controls to our userObj directly, like so:

Form Errors

In template-driven forms, we may handle two types of errors:

  1. Handle form submission with ngSubmit and error handling in the submit function.

  2. Add a feature that disables the submit button at first and enables it only after the form has been validated.

Sub-Form Components

The FormGroup is a FormControl collection. It may also include additional FormGroups.

When we use the <form>, the ngForm directive constructs the top Level FormGroup behind the scenes.

Using the ngModelGroup directive, we can create a new FormGroup. Let us add the street, city, and Pincode form control to the address FormGroup.

Simply wrap the fields within a div element with the ngModelGroup directive applied to it, as seen below:

Launch the app and submit it. The resulting item is seen below.

Validation

The validators in the model-driven method were defined via code in the component.

In the template-driven technique, validators are defined in our template through directives and HTML5 properties. Let's add validators to our form template.

Except for the language, all of the fields were necessary, so we'll just add the required attribute to those input fields.

Validation Styling

To provide visuals on the screen, we employ several Form Control States such as valid, touched, and dirty. These are the FormControl properties.

However, with template-driven forms in angular, no FormControl object is created within the component. So, to access FormControl, we may use one of the methods listed below.

1. Using .form property of ngForm

Using userForm.form.controls.firstName, we can get the title FormControl of userForm. We may retrieve the control status of the FormControl using this object, as illustrated below.

2. Using local template reference variable.

To access control state properties of title control, we need to go through myForm.form.controls.title.valid. Using the ngModel directive, we can make this shorter.

As shown below, we are creating a local reference to the title FormControl using the ngModel directive

Now, we can access the control state of the title using just firstName.valid, as shown below.

Both ways will give the same output.

Validation Messages

In terms of form validation messages, we may utilize them the same way as in model-driven forms. We may use the same HTML in our template-driven forms as long as we name the local reference variables the same as the form controls in the model-driven method, as seen below:

Submitting the Form

We may submit the form using the ngSubmit directive or on the Submit button's click event. Either option is acceptable.

Let's add ngSubmit to the form:

user-profile.component.html

Now, we will create one method inside the component.

user-profile.component.ts

Resetting the Form

As with the template-driven form, we may reset the form. As seen below,

Conclusion

  • Angular template-driven forms are the easiest way to create interactive form
  • Will have to import FormsModule and add it to the @NgModule imports array
  • Attaching the ngForm directive to the <form> tag will attach a form to FormsModule, and now it'll have all the properties
  • Creating dynamic forms is possible
  • Handling errors, domain models and reset forms becomes easy when using angular forms