In this video, let's see how the data binding is happening with the form fields. So far we have just created a basic HTML form, nothing related to Angular. The first step to start working with Angular forms is to import the FormsModule. So open app.module.ts and then import FormsModule. Let's also add FormsModule to the imports array.
Now if we go back to app.component.html, we still have what seems like a basic HTML form, but behind the scenes, Angular's magic is already happening. Anytime we use a form tag, Angular attaches an ngForm directive to the form tag, which gives us valuable information about that particular form. It tells what the values of the different form controls are and whether the values are valid or invalid.
And how do we get a hold of a reference to this ngForm directive? Using a template reference variable. So to the form tag, I'm going to add a template reference variable. I'm going to call it userForm and to this, I'm going to assign the string ngForm.
So the ngForm directive exports itself as the string ngForm, and by assigning it to a reference variable, we have a reference to the directive itself. Now I just mentioned that the directive gives us access to the values of the form controls. It does so using the value property. So in the HTML, I'm going to use interpolation to take a peek at the form control values. So double curly braces and then userForm.value and then pass it through the JSON pipe.
Now if I save this and take a look at the browser, you can see that we have an empty object. I start typing the name, which was, and it still is an empty object. You might be wondering why it doesn't work.
Now if we ask Angular why the value is an empty object, it is going to tell you, "Hey, I am not going to track every single form control in your HTML. Let me know which of the form controls have to be tracked, only then will I do that."
The Necessity of the name Attribute
And how do we let Angular know of the controls to be tracked? Using the ngModel directive. So to each of the form controls, let's place the ngModel directive. So to the input, ngModel, ngModel, ngModel. To the select tag, ngModel. To the radio buttons, ngModel. And finally for the checkbox. Let's save this and take a look at the browser.
Now if I start typing, we don't see the expected result. So if I open the developer tools, go to the console, you can see that we have an error. And the error is that if ngModel is used within a form tag, either the name attribute must be set or the form control must be defined as standalone. And we see that time preference works because we do have a name for time preference, but for rest of the form fields, we don't have a name attribute. So along with the ngModel directive, the name attribute is very much necessary.
Let's add the name attribute to each of the form controls. The first one is going to be name="userName". The second one, name="email". name="phone". name="topic". We already have the name timePreference on the radio button. And finally, name="subscribe" on the checkbox.
Now let's save this and go back to the browser. And right away you can see there is a difference in how the object is being displayed. All the form controls are present as properties of this particular object. Let's start filling in the form and see what happens. So enter a name and you can see that name is updated. Email, and you can see that email is updated. Similarly, phone gets updated. The select dropdown, select a value and then that gets updated. Select a time preference, you can see that that works as well. And finally select the checkbox and you can see that a value of true is set in the object. Uncheck and it changes to false.
How Different Control Values are Represented
So we are able to retrieve the different form control values by making use of ngForm and ngModel directives. Input values correspond to the text in the field, radio button values correspond to the value attribute, select tag corresponds to the value attribute if present, else it just corresponds to the text that is there, and finally checkbox corresponds to either true or false.
Grouping Fields with ngModelGroup
Now in addition to ngModel, Angular also provides the ngModelGroup directive. We use the ngModelGroup directive if we would like to group together or create a subgroup within a form. For example, consider an address. Address can have Street, City, State, and Postal Code. We can group all of those fields into an address object using the ngModelGroup directive. Let me quickly show you how the code looks. So I'm going to copy paste the HTML and go through the code.
So right at the very top, I'm going to paste the HTML. So as you can see, we have four input elements: one for Street, one for City, one for State, and finally Postal Code. And all the four elements are enclosed in a div tag that has the ngModelGroup directive. To the directive, we assign a name called address. Now if we go back to the browser, take a look at the form value, you can see that we have the individual field names: email, phone, topic, and so on. But at the start, we now have a group of properties, and that group is the address object. Address contains four different properties: Street, City, State and Postal Code. So if you ever want to group together form fields, make use of this directive. Now to understand template-driven forms, though, we really don't have to focus on the ngModelGroup directive. I also want to keep the form as short as possible, and that is why I am going to remove the code that we have just added.
Summary and Next Steps
But please do keep in mind when it comes to data binding in template driven forms, we have three directives: ngForm, ngModel, and ngModelGroup. All right, so we are able to bind data using the ngModel directive and we can send this bound data to the server when required using userForm.value. Although this works completely fine, a better approach is to bind the data to a user-defined model and send that model data to the server. Let's see how to do that in the next video.