Over a million developers have joined DZone.
{{announcement.body}}
{{announcement.title}}

Template-Driven Forms in Angular

DZone's Guide to

Template-Driven Forms in Angular

We take a look at what it means to be template-driven, and how to implement this programming concept into your Angular code.

· Web Dev Zone ·
Free Resource

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

Forms are the main building block of any application. We use forms for logins, registration, submitting help requests. So, whatever form we are developing must be user-friendly. For example, when something goes wrong, it should have an indication as to why, etc.

Coming to Angular Forms, Angular provides two approaches for developing forms which are Template Driven and Reactive. Let’s try to explore the template-driven approach in this article

Template Driven Forms

Template driven forms are simple forms which can be used to develop forms. These are called template-driven as everything that we are going to use in the application is defined in the template that we are defining along with the component. Let’s see, step-by-step, how we can develop and use these forms in the application.

1. Prerequisite

We need to import the FormsModule into the Application module file (i.e. app.module.ts).

Do the Import from: @angular/Forms.

The code snippet for that can be like this:

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import {FormsModule} from '@angular/forms'
import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,

Add that Module in the imports section of the application module:

  ],
  imports: [
    BrowserModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

All right, this is the basic import that we need to do. We are now ready to use the forms in our application. So, how we can pass the data from the HTML to the component?

Let's have a look at the code snippet for the form which we will be using here.

<div class="container">  
  <div class="row">  
      <div class="form_bg">  
          <form #regForm='ngForm' (ngSubmit)="Register(regForm)" >  
               <h2 class="text-center">Registration page</h2>  
              <br/>  
              <div class="form-group">  
                  <input type="text" class="form-control" placeholder="First Name" name="firstname" ngModel >   
              </div>  
              <div class="form-group">  
                  <input type="text" class="form-control"  placeholder="Last Name" name="lastname" ngModel >  
              </div>  
              <div class="form-group">  
                  <input type="email" class="form-control" id="email" placeholder="Email" name="email" ngModel>  

              </div>  
               <div class="form-group">  
              </div>  
              <br/>  
              <div class="align-center">  
                  <button type="submit" class="btn btn-default" id="register"  >Register</button>  
              </div>  
          </form>  
      </div>  
  </div>  
</div> 

The above code has some elements (first name, last name, and email) and the submit button that will submit our form. Now that our form is ready, we need to pass the value to the component.

The first step in using the forms is understanding the NgForm and the NgModel directives that we used in the above code.

NgForm

It is the directive which helps to create the control groups inside the form directive It is attached to the <form> element in the HTML and supplements the form tag with some additional features. Some interesting things we can say about the view is that whenever we use the directive in the application view we need to assign some selector to it; in this case, the form is the selector. Next, we need to consider the NgModel attribute that we have assigned to each HTML control. Let’s see what this attribute does.

NgModel

When we add the NgModel Directive to the control all the inputs are registered in the NgForm.

It creates the instance of the FormControl class from the Domain model and assigns it to the form control element. This control keeps track of the user information and the state and validation status of the form control.

The next important thing we need to consider is when we use the NgModel with the form tag, or, most importantly, when to make use of the name property of the HTML control with NgForm. When we look at the above snippet, every control has been assigned a name property and then we have added the ngModel attribute to the control.

Example:

<input type="email" class="form-control" id="email" placeholder="Email" name="email" ngModel>

The main functionality offered by NgForm and NgModel is that it allows us to retrieve all the values of the control associated with the form and then retrieve the overall state of the controls in the form.

To expose ngForm in the application, we need to use the following code:

<form # (ngSubmit)="Register(regForm)" >

In this, we are exporting the ngForm value in the local variable regform. Now, the question arises, is it necessary to use this local variable? The answer is no. We are exporting ngForm in the local variable just to use some of the properties of the form and these properties are as follows:

  1. regForm.Value: It will give the object containing all the values of the field in the form.

  2. regForm.Valid: This will give us the value indicating if the form is valid or not. If it is valid, the value is true, otherwise, the value is false

  3. regForm.touched: It will return true or false when one of the fields in the form is entered and touched.

  4. regForm.submitted: It checks whether the form is submitted or not; it returns a value of true and false.

In the above case, we have noticed that the Form Tag has no action method or attribute specified, so how should we post the data in the component?

Let’s have a look at the (ngSubmit)="Register(regForm)" bit of code. Here, we are using the concept of Event Binding. We are using binding to call the Register method in the component and, here, instead of submitting an event of the form, we are using (ngSubmit) which will make actual HTTP requests, instead of just submitting the form.

Now, when we look at the component we can see that:

import { Component, OnInit } from '@angular/core';  
import { NgForm } from '@angular/forms';  
@Component({  
  selector: 'app-formdemobasics',  
  templateUrl: './formdemobasics.component.html',  
  styleUrls: ['./formdemobasics.component.css']  
})  
export class FormdemobasicsComponent implements OnInit {  

  constructor() { }  

  ngOnInit() {  
  }  

  Register(regForm:NgForm){  
    console.log(regForm);  

  }  
}  

Here we have the method in the component, Register. It accepts the ngForm object and it will have all the values from the template and display them in the console.

Note: In combination with the name attribute, ngModel creates the abstraction over the form's state and it will automatically show up in the forms value collection (i.e. form.value).

Validations

Validations are an important aspect of programming. We cannot trust the user, that’s why we always want to validate the data. So, we use validations for two primary reasons:  to prevent the user from entering the wrong data; to show some proper value to the user telling them to add the proper data.

How do we validate the template driven forms then? The answer is by using the Angular set of common validators like minlengthmaxlengthrequired, and email. How do we assign controls to the validators? Well, again, it's very easy - we just need to add the validator directive to the control.

How we do this? Let's look at the template of the new sign up form that we have added code snippet for in the following snippet:

<div class="container">  
    <div class="row">  
        <div class="form_bg">  
            <form #form="ngForm" (ngSubmit)="registerUser(form)">  
                 <h2 class="text-center">Registration page</h2>  
                <br/>  
                <div class="form-group">  
                    <input type="text" class="form-control" placeholder="First Name" name="firstname" required ngModel>   
                </div>  
                <div class="form-group">  
                    <input type="text" class="form-control"  placeholder="Last Name" name="lastname" required ngModel>  
                </div>  
                <div class="form-group">  
                    <input type="email" class="form-control" id="email" placeholder="Email" name="email" email required ngModel #email="ngModel">  
                    <span class="help-bpx" *ngIf="email.touched && !email.valid ">Please enter the Email Value</span>  
                </div>  
                 <div class="form-group">  
                </div>  
                <br/>  
                <div class="align-center">  
                    <button type="submit" class="btn btn-default" id="register" [disabled]="!form.valid" >Register</button>  
                </div>  
            </form>  
        </div>  
    </div>  
</div> 

Let's see the sample for the basic validation required for the username:

<input type="text" class="form-control" placeholder="First Name" name="firstname" required ngModel>

What we need here is to show the red border whenever the first name is not entered in the control. How do we do that? Here, we can make use of the Angular CSS classes that will be applied and removed whenever the state of the form changes. The following are the classes which will be attached whenever the state is changed:

  1. ng-touched: Controls have been visited.

  2. ng-untouched: Controls have not been visited.

  3. ng-dirty: The control value has been changed.

  4. ng-pristine : The control value has not been changed.

  5. ng-valid: The control values are valid.

  6. ng-invalid: The control values are invalid.

So, in order to draw a border around the first name whenever the user visits the control and does not add any values, we need to use these classes.

To learn to use these classes, let's look at the snippet below:

input.ng-invalid.ng-touched  
{  
   border-color: red;  
}  

This is just the CSS logic that is adding the red border around the control and displaying it in the UI. Now, suppose we have a requirement to show the validation message for a particular control state.

Let's look at an example of that. In this example, we need to show the work 'Required' as well we check if the email entered is properly formatted or not.

<input type="email" class="form-control" id="email" placeholder="Email" name="email" email required ngModel #email="ngModel">
<span class="help-bpx" *ngIf="email.touched && !email.valid ">Please enter the Email Value</span>

Here we have used the template reference variable and assigned the ngModel (i.e. state of the control) to that variable. We have a span element which is displayed only when the email is entered but if the email is not valid for that, we have used ngIf in the span element. This is structural directive which will be displayed only if the email entered is invalid.

Deploying code to production can be filled with uncertainty. Reduce the risks, and deploy earlier and more often. Download this free guide to learn more. Brought to you in partnership with Rollbar.

Topics:
angular 2 ,web dev ,angular ,web application development

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}