Model driven forms - lordoftheflies/angular-essential-training GitHub Wiki

The model-driven or reactive approach is another way to handle building forms in Angular. It has a lot of similarities to the template driven approach but the big difference is the form is built in the component class. That allows you to have a contract that your form needs to adhere to, the ability to set up validation rules, subscribed to field value changes and ultimately unit tests your form logic without any UI layer. So template driven gives you an easy way to get up and running. Whereas model driven allows you to take your forms wherever they need to go. Let's refactor the mediaItemForm to be model driven or ReactiveForms based. So, model-driven forms are built using the ReactiveForms module instead of the FormsModule. We need to update the app module to import and use that instead of FormsModule. Now, just so you know, it is possible to import both of these together in the case where your module is making use of both template and model-driven forms or ReactiveForms. Okay, in the media-item-form.component.ts file, we are going to create a FormGroup object that represents the form. Remember from the lesson on the template driven approach that the Angular form system is working with a FormGroup. That's important FormGroup which is found in the Angular forms scoped package. We need a class property for the form. So let's add that naming it form. We can also use some TypeScript here to declare the type by adding a colon, then the FormGroup type then a semi-colon. Next we need to initialize the form property to a new form group. We will do this in an Angular lifecycle method called ngOnInit. While we could put this in the constructor, it is preferable to use the lifecycle events because it makes the code easier to unit test. To leverage a life cycle event you just need to add a known function name to your class and Angular will handle calling it if it exists on your class. There are several lifecycle function supported. You can check the angular.io documentation site for a list of those. And we can also make use of a TypeScript interface here named OnInit that Angular provides to help enforce the implementation. So that's add OnInit to the import statement from Angular core then add implements OnInit after the class name. Then we can add an ngOnInit method. And in the function body we set this.form equal to a new FormGroup. FormGroup expects to be called with an object structure that has properties named for the controls that will be in the group set to a value of a new control. Let's import FormControl. so we can new up some controls. FormControl is in the Angular forms scoped package as well. So he add that to the import list. And then in the parentheses for FormGroup recreate an object literal and we set up the form fields as property names and setting their value equal to a new FormControl object. FormControl can take in a default value as the first argument call. So we can set the medium to default to movies and set the rest of the default to empty strings. With the a form model created, we can flip over to the media-item-form.component.html file and we can make a few changes. First we need to tell Angular that we have a model for the form so we can remove the local template variable mediaItemForm and replace it with a directive binding of bracket formGroup bracket setting that equal to form. And then in the onSubnit call we can call .value of form instead of mediaItemForm. The other thing we need to do is change out the ng model directive from the form fields. Since we created the form controls for these fields in the formGroup in the component class, we just need to wire up the form fields to the appropriate controls from the formGroup. This can be done with a FormControl named directive. This directive can be added to a form field element and be set to a string value that matches the name of the corresponding FormControl created in the component class. With all those wired up, if we head over to the browser we can see that the form has a default value for medium of movies like we configured and if we fill out the form we see the same expected behavior in the console log.