Converting a Form from a Template Driven approach to Reactive approach in MEAN Stack
We learned how we could add an input file button into our angular app in our previous section. We used the file input and an angular material button. In this section, we will register the input with our form. To do that, we need to convert our form from a template-driven approach to a reactive approach. In this section, we will also learn how to convert our form from a template-driven approach to a reactive approach.
In the reactive approach, we define everything in our typescript code and tell angular which of our defined controls maps to which input.
We will use the following steps to do that:
1) If we want to use the reactive approach, we need to import ReactiveFormsModule rather than importing FormsModule from @angular/ forms into our app.module.ts. The FormsModule unlock the template-driven approach. We will add this module into the imports array like this:
2) We need to disable the ngModel from our post-create.component.ts We will get rid from the ngModel and the validators. After removing the ngModel from our form, our html code will look like this:
Above, we also removed the argument we passed on the onAddPost() method because we don't have access to the form in the template anymore.
3) In our typescript file, we need to change the way we created our form. So, we will create our form programmatically in a typescript file. We will create form and store that in a "form" property, which will be of type FormGroup. So, we need to import the FormGroup from the @angular/forms and remove the ngForm.
FormGroup is the top-level object for a form and groups all the control of it. We can also have sub-groups in a form and then group controls within a form, but the form overall is just one big group, and we will work with that.
4) We will create the form property of type FormGroup in the following way:
We got the form, but it is undefined. So, we need to initialize which controls we have, and we will do that in ngOnInit. We will reach out the ngOnInit(), and at the beginning of this method, we will do the initialization in the following way:
In the above code, the FormControl creates a single control in the form. In the FormControl() method, we passed a couple of arguments. The first argument in the FormControl function is the beginning form state. We passed null as a first argument because we want to start with null by default to have an empty input.
We will do the same thing for the content like this:
Now, we got the same form as before basically, and of course, the form is not done yet. The things that are missing there are the connection to the template and the part where we can pre-populate these controls with concrete values if we are editing a post. Because we set the starting values to null, but that will be correct only if we are creating a new post.
6) Now, we initialized the values in case we got a loaded post. When we save the post, there will be no need to get the form as an argument. Instead of this, we have our own form object registered as a property in our class. So, we will access it with this.form. We will use form for the invalid property, access the value property, and access the title and content value in the updatePost() method.
7) Now, to reset the form we will call the this.form.reset() method rather then calling resetForm() method in the following way:
8) Now, we are done with the typescript code, and the thing which is missing is the part where we synchronize our HTML code to our typescript. For doing this, we will go back to our post-create.component.ts file, and here we remove the name because angular gives the flexibility of defining no name. So, instead of relying on something, we add a special directive. However, first of all, we add a directive, i.e., formGroup directive to our overall form and this FormGroup directive takes our form object. This form object tells angular that the form we created in typescript is the HTML form.
9) Now, on the input, we will use the formControlName directive and the name of the control is the same as we defined in the post-create.component.ts file in the following way:
Now, we got the title.invalid error in the <mat-error>. So, we will hook up this error. We need to access our title form control by accessing the overall form and using the get() method. This method gives us access to control. In this method, we pass the control name as a title in the following way:
We will do both the things for our text area like this:
Now, if we run the angular app, we will have a working form again.
We successfully converted the form from a template-driven approach to a reactive approach. In the next section, we will add the image controls to store the image.