top

Search

Angular JS Tutorial

Forms are one of the most important and crucial parts of a web application. While most of the time the user uses the mouse to click here and there in the application to navigate between components or even pages, it is a form that brings in useful information from the user to us. This information is typically crucial to a business, that’s why there was a form in the first place, right?On the surface, the forms look very simple and easy to implement. They accept user inputs and pass that input to a web-server somewhere where the information is stored or processed. But this is definitely not the case. Apart from taking user inputs, the forms also handle the following issues.Generally, the data entered by the user is used in many ways, both on the client and on the server. This information can be used, for example, to present a user with an extra 10% discount.Sometimes, it is important to make some changes to the page, based on the values entered in the form.Users can enter unexpected values in the input fields, so the forms needs to validate everything the users have entered.Apart from validating the field inputs, the forms also need to specify clear and concise messages to the users explaining to them what went wrong.Sometimes, a field is dependent on another field. In such situations, the field inputs are watched and based on the values, new fields are displayed to the user.So that’s a lot for a tiny little form. Thankfully, Angular has tools to help with all of these things.FormControls encapsulate the inputs in our forms and give us objects to work with them.Validators give us the ability to validate inputs, any way we’d like.Observers let us watch our form for changes and respond accordingly.Before we get started with building forms, let’s install Bootstrap so that we get to see some beautiful forms. Bootstrap is a CSS framework that will help us use some pre-built CSS classes and therefore, we can save some time and focus on the Angular part.To install Bootstrap into the project, open index.html file and add the following link tag to the head section. <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">Last, but not the least, to use FormControl, make sure you have imported the ReactiveFormsModule and FormsModule into your AppModule.Save the file and restart the dev server. That’s it! So let’s get started with building forms in Angular.FormControl and FormGroupA FormControl represents a single input field in the form. It is the smallest unit of an Angular form. FormControls encapsulate the field’s value, and states such as being valid, dirty (changed), or has errors.For instance, here’s how we might use a FormControl in TypeScript:We just declare an object of type FormControl and then initialize it in the constructor. The FormControl constructor takes an optional initial value of the control. Here we passed in Knowledge which is a simple string. Next, we use this FormControl in the component’s template using the formControl directive.Most of the HTML code is simply Bootstrap code that adds some styling to the Form. The key here is the usage of formControl directive which is set to the name of the FormControl object that we created in the previous step, fnameControl. Let’s save everything and see how it looks like.Nice, right? We have a form with just one input field and it has the initial value “Knowledge”. That’s because we used that value to be set as the initial value for the FormControl. Very quickly, let’s create another one for the Last Name and then one for the Email. The final Typescript code will look something like this.And this is how the final HTML looks like.Let’s looks at the output now.Awesome! That’s how you can use FormControls. To access the values of these FormControls in the TS (after the user has changed or entered them), you can the value property to access.fnameControl.value // KnowledgelnameControl.value // HutemailControl.value // contact@knowledgehut.comJust like the form we create, most forms have more than one field, so we need a way to manage multiple FormControls. If we wanted to check the validity of our form, it’s cumbersome to iterate over an array of FormControls and check each FormControl for validity. FormGroups solve this issue by providing a wrapper interface around a collection of FormControls.Here is how you would use a FormGroup in Typescript. Instead of declaring three different FormControls, we declare only one FormGroup.Finally, we need to make relevant changes to the HTML as well in order to use this FormGroup named personFormGroup.In the HTML, first, we are now using the formGroup directive and binding it to the created FormGroup which is personFormGroup. Secondly, we replace the formControl binding with the directive formControlName directive which takes the name of the FormControl as defined in TypeScript. That’s it.Save everything and test if the form looks okay.If everything went okay, you should see the same form working again. Perfect! To access the values of the fields in the form, you can simply use the value property on the FormGroup object. personFormGroup.value gives the value  /*   {    "fname": "Knowledge",   "lname": "Hut",  "email": "contact@knowledgehut.com"   }   */  The value is a JSON object with key value pairs. Simple and elegant. NgForm and NgSubmitThe form that we have accepts user input but we cannot really do anything with the data as of now. We do not have a way to submit the form’s data to a method and then process it later, which is why we have created the form in the first place. We can do this with the ngSubmit event. In the following code you can see that we have bound the ngSubmit event to a method called onFormSubmit(). <form [formGroup]="personFormGroup" (ngSubmit)="onFormSubmit()"> This will ensure that the method is invoked as soon as the form is submitted. Next, we need to add a submit button to the form at the bottom and also write the method onFormSubmitted in the Typescript class. So, first we add the button at the bottom inside the form. <button type="submit" class="btn btn-primary float-right">Submit</button> And then we create the method. onFormSubmit() {  console.log(this.personFormGroup.value);   } This method, as of now, just logs the form data to the console. Let’s test this out.Works just fine! But there is a little more here than what meets the eye. There is an NgForm directive that has been attached to the Form. This happens because we are using the FormsModule. What this means is that if you import FormsModule, NgForm will get automatically attached to any <form> tags you have in your view. This is really useful but potentially confusing because it happens behind the scenes.  You can however, modify the above code a little bit, to make think more clear and readable. We use a template variable to as a reference to the Form and then we pass it to the onSubmit method as an argument. <form [formGroup]="personFormGroup" #f="ngForm" (ngSubmit)="onFormSubmit(f.value)"> #f="ngForm" is a way using a template variable (f in this case) as a reference to the form. Next, we change the method signature and body as shown below. onFormSubmit(formData: any) {  // console.log(this.personFormGroup.value);  console.log(formData);  } Now the method receives the form’s data as an argument and we no longer need to access the form data using the object personFormGroup.  It is a good practice This separates our method completely from the form and makes it independent. The method is now reusable and can work for any form as long as it receives the form’s data as an argument. FormBuilder Building our FormControls and FormGroups implicitly using ngForm and ngControl is convenient, but doesn’t give us a lot of customization options. A more flexible and common way to configure forms is to use a FormBuilder.  FormBuilder is an aptly-named helper class that helps us build forms. As you recall, forms are made up of FormControls and FormGroups and the FormBuilder helps us make them. Let’s add a FormBuilder to our previous example.  constructor(private fb: FormBuilder) {  this.personFormGroup = this.fb.group({  fname: ['Knowledge'],  lname: ['Hut'],  email: ['contact@knowledgehut.com']  });  } We inject FormBuilder by creating an argument in the constructor of our component class and then use the group() method to build the form. We specify the form fields as key value pairs where the values are arrays with the default values of the fields respectively. We will later add validators as the second and third items in these arrays. We haven’t talked much about dependency injection (DI) or how DI relates to the hierarchy tree, so that last sentence may not make a lot of sense. We talk a lot more about dependency injection in a future module, but  at a high level, Dependency Injection is a way to tell Angular what dependencies this component needs to function properly. Save the files and everything should work just as it was working before using the formGroup and formControlName directives in the template. But now, we are using a FormBuilder to build our form. Let’s add validations to this form. For now, let us assume that only first name is required and last name is not required. Both these fields need to be valid strings. The second name, however, can be left blank. The email field is required and should contain a valid email.  First, let’s bring the in the Validators class from the same @angular/forms module. import { FormGroup, FormBuilder, Validators } from '@angular/forms'; Next, let’s modify the FormBuilder like this. this.personFormGroup = this.fb.group({  fname: ['Knowledge', Validators.required ],  lname: ['Hut'],  email: ['contact@knowledgehut.com', Validators.email ]  }); We have used the required and email validators from the Validators class and these will ensure that the fname field is required and the email field is a valid email, respectively. Notice that we have passed Validators for each field a the second element to the array. You can combine multiple Validators together like this. this.personFormGroup = this.fb.group({  fname: ['Knowledge', Validators.compose(  [  Validators.required,   Validators.minLength(5)  ])  ],  lname: ['Hut'],  email: ['contact@knowledgehut.com', Validators.email ]  }); In the above code, to combine more than one Validators together, we are using Validators.compose method that takes an array of Validators. Now the first name needs to be entered by the user and it has to be at-least 5 characters long. Now that we have added validations to our forms, we need to see if the form is in a valid state or not. To do that, let’s add some code to the bottom of the HTML template at the bottom. <div>  <div>Form Data: {{ f.value | json }}</div>  <div>Valid {{ f.valid }}</div>  <div>Invalid {{ f.invalid }}</div>  <div>Touched {{ f.touched }}</div>  <div>Dirty {{ f.dirty }}</div>  </div> This will allow us to see the value of the form as a JSON object (hence the json pipe - we will talk about it in the next lesson), and some other properties that will tell us about the state of the form. Save everything and test the app in the browser.As you can see that initially all the fields are valid so the valid property of the form is true and invalid is false. Pretty straight-forward.The value of touched is false because have not interacted with the form yet.Once we click on any input field, touched will become true and once we type anything in any input, dirty becomes true as well.Try deleting the first name completely. The form fields will change completely to look like the following.So that’s how validations work. You can use these properties to make your form interactive. Let’s look at an interactive form.Change the code for the submit button in the HTML to the one below.<button type="submit" [disabled]="f.invalid" class="btn btn-primary float-right">Submit</button>We have bound the disabled property of the button to the invalid property of the form in such a way that if the form is invalid, the button will automatically be disabled, therefore not allowing the users to submit the invalid form.That’s it about the forms in Angular. Feel free to play around with different properties and use other directives like NgIf in combination with the form properties to show and hide content.
logo

Angular JS Tutorial

Forms in Angular

Forms are one of the most important and crucial parts of a web application. While most of the time the user uses the mouse to click here and there in the application to navigate between components or even pages, it is a form that brings in useful information from the user to us. This information is typically crucial to a business, that’s why there was a form in the first place, right?

On the surface, the forms look very simple and easy to implement. They accept user inputs and pass that input to a web-server somewhere where the information is stored or processed. But this is definitely not the case. Apart from taking user inputs, the forms also handle the following issues.

  • Generally, the data entered by the user is used in many ways, both on the client and on the server. This information can be used, for example, to present a user with an extra 10% discount.
  • Sometimes, it is important to make some changes to the page, based on the values entered in the form.
  • Users can enter unexpected values in the input fields, so the forms needs to validate everything the users have entered.
  • Apart from validating the field inputs, the forms also need to specify clear and concise messages to the users explaining to them what went wrong.
  • Sometimes, a field is dependent on another field. In such situations, the field inputs are watched and based on the values, new fields are displayed to the user.

So that’s a lot for a tiny little form. Thankfully, Angular has tools to help with all of these things.

  • FormControls encapsulate the inputs in our forms and give us objects to work with them.
  • Validators give us the ability to validate inputs, any way we’d like.
  • Observers let us watch our form for changes and respond accordingly.

Before we get started with building forms, let’s install Bootstrap so that we get to see some beautiful forms. Bootstrap is a CSS framework that will help us use some pre-built CSS classes and therefore, we can save some time and focus on the Angular part.

To install Bootstrap into the project, open index.html file and add the following link tag to the head section. 

<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" crossorigin="anonymous">

Last, but not the least, to use FormControl, make sure you have imported the ReactiveFormsModule and FormsModule into your AppModule.

Angular Forms code

Save the file and restart the dev server. That’s it! So let’s get started with building forms in Angular.

FormControl and FormGroup

A FormControl represents a single input field in the form. It is the smallest unit of an Angular form. FormControls encapsulate the field’s value, and states such as being valid, dirty (changed), or has errors.

For instance, here’s how we might use a FormControl in TypeScript:

Angular Forms code

We just declare an object of type FormControl and then initialize it in the constructor. The FormControl constructor takes an optional initial value of the control. Here we passed in Knowledge which is a simple string. Next, we use this FormControl in the component’s template using the formControl directive.

Angular Forms code

Most of the HTML code is simply Bootstrap code that adds some styling to the Form. The key here is the usage of formControl directive which is set to the name of the FormControl object that we created in the previous step, fnameControl. Let’s save everything and see how it looks like.

Angular Forms in Angular

Nice, right? We have a form with just one input field and it has the initial value “Knowledge”. That’s because we used that value to be set as the initial value for the FormControl. Very quickly, let’s create another one for the Last Name and then one for the Email. The final Typescript code will look something like this.

Angular Forms code

And this is how the final HTML looks like.

Angular Forms code

Let’s looks at the output now.

Angular Forms in Angular

Awesome! That’s how you can use FormControls. To access the values of these FormControls in the TS (after the user has changed or entered them), you can the value property to access.

  • fnameControl.value // Knowledge
  • lnameControl.value // Hut
  • emailControl.value // contact@knowledgehut.com

Just like the form we create, most forms have more than one field, so we need a way to manage multiple FormControls. If we wanted to check the validity of our form, it’s cumbersome to iterate over an array of FormControls and check each FormControl for validity. FormGroups solve this issue by providing a wrapper interface around a collection of FormControls.

Here is how you would use a FormGroup in Typescript. Instead of declaring three different FormControls, we declare only one FormGroup.

Angular Forms code

Angular Forms code

Finally, we need to make relevant changes to the HTML as well in order to use this FormGroup named personFormGroup.

Angular Forms code

In the HTML, first, we are now using the formGroup directive and binding it to the created FormGroup which is personFormGroup. Secondly, we replace the formControl binding with the directive formControlName directive which takes the name of the FormControl as defined in TypeScript. That’s it.

Save everything and test if the form looks okay.

Angular Forms in Angular

If everything went okay, you should see the same form working again. Perfect! 

To access the values of the fields in the form, you can simply use the value property on the FormGroup object. 

personFormGroup.value gives the value 
/*  
{   
"fname": "Knowledge",  
"lname": "Hut", 
"email": "contact@knowledgehut.com"  
}  
*/  

The value is a JSON object with key value pairs. Simple and elegant. 

NgForm and NgSubmit

The form that we have accepts user input but we cannot really do anything with the data as of now. We do not have a way to submit the form’s data to a method and then process it later, which is why we have created the form in the first place. We can do this with the ngSubmit event. 

In the following code you can see that we have bound the ngSubmit event to a method called onFormSubmit(). 

<form [formGroup]="personFormGroup" (ngSubmit)="onFormSubmit()"

This will ensure that the method is invoked as soon as the form is submitted. Next, we need to add a submit button to the form at the bottom and also write the method onFormSubmitted in the Typescript class. 

So, first we add the button at the bottom inside the form. 

<button type="submit" class="btn btn-primary float-right">Submit</button> 

And then we create the method. 

onFormSubmit() { 
console.log(this.personFormGroup.value);  
} 

This method, as of now, just logs the form data to the console. Let’s test this out.

Angular Forms in Angular

Angular Forms in Angular

Works just fine! But there is a little more here than what meets the eye. There is an NgForm directive that has been attached to the Form. This happens because we are using the FormsModule. What this means is that if you import FormsModule, NgForm will get automatically attached to any <form> tags you have in your view. This is really useful but potentially confusing because it happens behind the scenes.  

You can however, modify the above code a little bit, to make think more clear and readable. We use a template variable to as a reference to the Form and then we pass it to the onSubmit method as an argument. 

<form [formGroup]="personFormGroup" #f="ngForm" (ngSubmit)="onFormSubmit(f.value)"> 

#f="ngForm" is a way using a template variable (f in this case) as a reference to the form. Next, we change the method signature and body as shown below. 

onFormSubmit(formData: any) { 
// console.log(this.personFormGroup.value); 
console.log(formData); 
} 

Now the method receives the form’s data as an argument and we no longer need to access the form data using the object personFormGroup.  

It is a good practice This separates our method completely from the form and makes it independent. The method is now reusable and can work for any form as long as it receives the form’s data as an argument. 

FormBuilder 

Building our FormControls and FormGroups implicitly using ngForm and ngControl is convenient, but doesn’t give us a lot of customization options. A more flexible and common way to configure forms is to use a FormBuilder.  

FormBuilder is an aptly-named helper class that helps us build forms. As you recall, forms are made up of FormControls and FormGroups and the FormBuilder helps us make them. 

Let’s add a FormBuilder to our previous example.  

constructor(private fb: FormBuilder) { 
this.personFormGroup = this.fb.group({ 
fname: ['Knowledge'], 
lname: ['Hut'], 
email: ['contact@knowledgehut.com'] 
}); 
} 

We inject FormBuilder by creating an argument in the constructor of our component class and then use the group() method to build the form. We specify the form fields as key value pairs where the values are arrays with the default values of the fields respectively. We will later add validators as the second and third items in these arrays. 

We haven’t talked much about dependency injection (DI) or how DI relates to the hierarchy tree, so that last sentence may not make a lot of sense. We talk a lot more about dependency injection in a future module, but  at a high level, Dependency Injection is a way to tell Angular what dependencies this component needs to function properly. 

Save the files and everything should work just as it was working before using the formGroup and formControlName directives in the template. But now, we are using a FormBuilder to build our form. Let’s add validations to this form. 

For now, let us assume that only first name is required and last name is not required. Both these fields need to be valid strings. The second name, however, can be left blank. The email field is required and should contain a valid email.  

First, let’s bring the in the Validators class from the same @angular/forms module. 

import { FormGroup, FormBuilder, Validators } from '@angular/forms'; 

Next, let’s modify the FormBuilder like this. 

this.personFormGroup = this.fb.group({ 
fname: ['Knowledge', Validators.required ], 
lname: ['Hut'], 
email: ['contact@knowledgehut.com', Validators.email ] 
}); 

We have used the required and email validators from the Validators class and these will ensure that the fname field is required and the email field is a valid email, respectively. Notice that we have passed Validators for each field a the second element to the array. 

You can combine multiple Validators together like this. 

this.personFormGroup = this.fb.group({ 
fname: ['Knowledge', Validators.compose( 
[ 
Validators.required,  
Validators.minLength(5) 
]) 
], 
lname: ['Hut'], 
email: ['contact@knowledgehut.com', Validators.email ] 
}); 

In the above code, to combine more than one Validators together, we are using Validators.compose method that takes an array of Validators. Now the first name needs to be entered by the user and it has to be at-least 5 characters long. 

Now that we have added validations to our forms, we need to see if the form is in a valid state or not. To do that, let’s add some code to the bottom of the HTML template at the bottom. 

<div> 
<div>Form Data: {{ f.value | json }}</div> 
<div>Valid {{ f.valid }}</div> 
<div>Invalid {{ f.invalid }}</div> 
<div>Touched {{ f.touched }}</div> 
<div>Dirty {{ f.dirty }}</div> 
</div> 

This will allow us to see the value of the form as a JSON object (hence the json pipe - we will talk about it in the next lesson), and some other properties that will tell us about the state of the form. Save everything and test the app in the browser.

As you can see that initially all the fields are valid so the valid property of the form is true and invalid is false. Pretty straight-forward.

The value of touched is false because have not interacted with the form yet.

Once we click on any input field, touched will become true and once we type anything in any input, dirty becomes true as well.

Try deleting the first name completely. The form fields will change completely to look like the following.

So that’s how validations work. You can use these properties to make your form interactive. Let’s look at an interactive form.

Change the code for the submit button in the HTML to the one below.

<button type="submit" [disabled]="f.invalid" class="btn btn-primary float-right">Submit</button>

We have bound the disabled property of the button to the invalid property of the form in such a way that if the form is invalid, the button will automatically be disabled, therefore not allowing the users to submit the invalid form.

Angular Forms in Angular

That’s it about the forms in Angular. Feel free to play around with different properties and use other directives like NgIf in combination with the form properties to show and hide content.

Leave a Reply

Your email address will not be published. Required fields are marked *

Comments

somasundarapandian

great learning blog!

michael

great blog!

Suggested Tutorials

Node JS Tutorial

Build various types of web applications,command-line application,etc.
Node JS Tutorial

Build various types of web applications,command-line application,etc....

Read More

JavaScript Tutorial

JavaScript is a dynamic computer programming language for the web. JavaScript was first known as LiveScript. Later on, Netscape changed its name to JavaScript because of its popularity and the excitement generated by it. JavaScript is lightweight and most commonly used as a part of web pages supported by most web browsers like Chrome, Internet Explorer, Opera, Safari, Edge, and Firefox.
JavaScript Tutorial

JavaScript is a dynamic computer programming language for the web. Jav...

Read More