Introduction to Angular Forms

By March 6, 2020Angular
Introduction to Angular Forms

With Angular there are 2 main ways to create HTML forms

  • Template Driven Forms
  • Reactive Forms (also called as Model Driven Forms)

Each of these approaches have some of their own advantages and disadvantages. Template Driven forms are useful when we want to create a simple form i.e. form which has lesser number of fields and most the fields on the form are static. Reactive forms are useful when your form is complex or has dynamic fields or you want to do cross-field validation.

Template Driven Forms

For Template driven forms, we can us angular directives ngForm and ngModel. Here is simple template drive form html.

Here is simple template drive form html.

We have declared a simple form with three controls: First Name , Last Name and Email, All are mandatory fields.The Submit button is only enabled when both required fields have values. On form submit it will call controller method saveEmployee.

Angular is tracking three form field states

  • touched or untouched
  • valid or invalid
  • pristine or dirty

Angular also checks the validity state of the whole form. Form valid status is used to enable or disable the submit button. This functionality is common for template-driven and reactive forms.

Angular directive ngModel is used for data binding. It keeps the HTML element value and it’s corresponding component property in sync.

Note the following line of code.

Here #employeeForm is called as template reference variable. We have assigned “ngForm” as the value for the template reference variable employeeForm. Hence employeeForm variable holds a reference to the form. In Angular it automatically attaches the ngForm directive to the form, when it sees a form tag. The ngForm directive provides additional features to the form element. It holds all the controls in the form that we create with ngModel directive and name attribute, and monitors their properties like value, dirty, touched, valid etc. The form also has all these properties.

In this case, because both validation and binding are done at the level of the template in a declarative way, So this is called template-driven forms,.

Here we have set ngModel directive to “firstName”, but we do not have ” firstName ” property in the component class. Angular automatically creates ” firstName ” property using the value of the “name” attribute of the HTML input element. This is why “name” attribute is also required when we use ngModel directive. In case we forget to provide “name” attribute, angular gives the following error:

If ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as ‘standalone’ in ngModelOptions.

If we want an input element to be tracked by the form, we need to include both the name attribute and ngModel directive. Otherwise that input element won’t be the part of the Form model created by Angular.

Here is the code of a controller for this html. It simply logs value of employeeForm.

The ngForm directive is provided by Angular FormsModule. So we will have to import the FormsModule in our AppModule file (app.module.ts).

Here is app.module.ts

Advantages and Disadvantages of Template Driven Forms

As this is a quite simple example, we might not realize it, but adding all validations in the template becomes hard to read. Also as validation logic becomes complex it becomes difficult to handle it in the template.

The advantage of this approach is simplicity, and it’s enough to build most of the forms. Disadvantage is, the form validation logic cannot be unit tested.

Reactive (Model Driven) Forms

Reactive forms give us freedom to build the form completely in code. This is more flexible and has many advantages over template forms. For example, it is easy to add form input elements dynamically and change validation logic at run-time based on different conditions in code. It is also easy to unit test as most of the logic and validation is in the component class. The only downside of reactive forms is, for reactive forms we need to write more code than template forms. With a reactive form, we create all form controls in the component class code. Let us try to understand this with a simple form with just 3 form controls as shown below

Here is the modified HTML. Notice the use of formGroup and formControlName directives in the <form> element and the 3 input elements.

Here is the controller code for the same.

Two classes that we commonly use to create a form control tree are FormGroup and FormControl. As the names imply to create a form with a group of controls, we create an instance of FormGroup class and to create each input element i.e a form control, we create an instance of FormControl class

To bind the view template to the form group model we created in the component class, we make use of the following 2 directives provided by Angular ReactiveFroms module.

formGroup formControlName

If we try to execute this code, we will get the following error

Can’t bind to ‘formGroup’ since it isn’t a known property of ‘form’

This is because, the 2 directives (formGroup and formControlName) are in the ReactiveForms module, but we have not yet imported it in our root module. So in the

AppModule (app.module.ts file), import ReactiveFormsModule and include it in the imports array.

Our AppModule code will be as follows.

You are probably wondering what we gained here.
We can now move validations part to the controller as follows.

We can now set values of the controls from the controller. We can also unit test the form validation logic. We can edit data for the form in controller. We can use setValue() and patchValue() function to change the entire form data or part of the data from controller.

To shorten code required to create the form, we can also use FormBuilder class. But we need to use FormBuiler as a service.

Form group accepts both form control and form group instances as children. This allows us to create a nested form group

For e.g. here is sample code to create nested form group using FormBuilder

We also need to change this in the html template for the nested address field as follows

 

 

 

 

 

 

 

Alphonso Global

Author Alphonso Global

More posts by Alphonso Global

Leave a Reply