This course has been updated! We now recommend you take the Angular 13 Fundamentals course.
Transcript from the "Template Forms" Lesson
[00:00:00]
>> Let's move on to the next module, which is template forms. And so the reason or the impetus behind this is we're kind of dumping this object into the DOM. But that's not super helpful. And so, what we want to do is we want to introduce the ability to manipulate this form.
[00:00:29] And so, this is where we're going to replace this with, in this case, a basic form using just a template binding. So, if we go into. The courses component, and into our course details, we're going to now take this and we're going to start to convert this into a form.
[00:01:04] When you are using forms, much to my embarrassment, make sure that you import the forms module as well as if you're doing reactive forms, make sure you import that module. So when you start to work with forms, what you need to do is in your top level module, usually you need to import forms module, or if you're doing reactive forms, you need to import reactive forms module.
[00:01:37] Because what will happen is, if we take this out and I tried to access, for instance, NgModule or any of the form stuff underlying, one, I'm going to throw an air, two, on live television it's not going to work. Now, another thing we'll elaborate a little bit more when we get into component testing, but when, because I now have a dependency on forms module.
[00:02:04] For, or we're going to add it into the courses component, that when I go to write the test, I need to make sure to add that module into the test. So, one of the biggest things when you're testing, really anything is satisfying the dependencies for that particular unit under test.
[00:02:31] And so, just kind of putting that is a placeholder in there. So, in our component, let's get started. All right. So, what we're going to do is I'm going to just take, and I'm going to wrap, the card content and the card actions in a form. All right?
[00:03:01] And because we're now using a form module, Angular is going to do some stuff under the hood. One of these things that it's going to do is it's going to create, essentially a form controller which can then contain other form controllers. Which manages not only the data of the form, but the correctness of the form.
[00:03:28] And so, this is where, when you start to think about forms, it's important to, one, realize that you're not only manipulating the data and you need to reflect that. But as well, you need to think about, is this form state correct enough for me to do an additional action on it?
[00:03:54] So, the question is, am I going to talk about the pros and cons of template forms versus reactive forms? Yes. I would definitely get into that a bit later today. But in the meantime, let's see this in action. So, what I'm gonna do is I'm going to create a local template variable and I'm just gonna call this form, and then within this, I'm going to just do ngForm.
[00:04:24] Now, what this does, or allows us to do is, now it's under the hood, Angular is creating a form control to kind of monitor what is happening with the form. And then, we're essentially assigning that reference to a local template variable, which we'll see in just a moment.
[00:04:45] But in order for this to work, I kind of need to add in a Form control. So, let's take, and I'm going to delete this here, and let's start to build out this form. Now that I have this form defined, I'm going to create a mat form field.
[00:05:09] So this is a Angular Material mechanism. And then within this, I'm gonna create a text input. So, we'll just go input, and we'll start to flesh this out. Now, what you have to be super careful of is making sure that you get the correct case, so it's not staircase but it is camel case.
[00:05:39] Trust me, from experience, if you mess this up, it will be incredibly embarrassing. So, make sure that you use camel case, not staircase. And then, because we have an input, we'll go ngModel, and we are going to bind two Current. Course. Or, I think it's actually selected course, there we go, title.
[00:06:09] And, I'm gonna break this to a separate line. [LAUGH] And, we're also going to type equals text, and name equals title. So, let's stop there, and let's see if we can even get this to render. So, over here, we got the title, but we have an error. We cannot read property of title because it's null.
[00:06:46] And so, there's a couple ways to solve this. But what I recommend is to start with, especially when dealing with a form, start with an empty object, that you can then bind to until you have a selected object that you're going to edit. And so, a lot of times I will reuse the same form to create and update an object.
[00:07:08] And so, what we're going to do is we're going to hop into our component, and we're going to create a resetSelectedCourse method. And we're going to create an empty, course. And this is going to have an id of null, I'll just fix this real quick. Checking on my Zoom room to make sure that they're not throwing their hands in the air like they just don't care.
[00:07:46] So id is null, good, description here, and we have percentComplete We'll go with 0, and it looks like I spelt that right and for whatever reason, I know why, false. All right. And then, what we're going to do is we're just going to go this selectedCourse equals emptyCourse.
[00:08:32] All right. Now, we're going to take a moment. And I want to touch on a component topic that we haven't gotten to just yet. And that's lifecycle hooks. And so, within a component, there are a variety of things that happen within its lifecycle, it's created, is destroyed. It's initialized, a number of things that its bindings are updated, etc.
[00:08:57] And so, within every component, there are what we call lifecycle hooks that allow us to tap into those lifecycle events. And so, when you generate a new component, what you will see is you have this method here for instance ngOnInit. So, this is the most common life cycle hook, and this is fired when your component is essentially initialized, or all of the bindings have been satisfied and so, you'll see here in ngOnInit.
[00:09:33] And, it's really considered a best practice that if you're using a lifecycle hook, that you add the interface, or you implement the interface to the component. So if I took this off, just for a second, you'll see that this should get angry. And so it's saying, you did not implement OnInit.
[00:09:53] So, you are basically in violation of this interface contract. And so, the reason why you especially want ngOnInit is that if you put logic in a constructor, when is it fired? Well, immediately. You have no control over when that code is executed. It's also very hard to test.
[00:10:14] With ngOnInit, if you're waiting for asynchronous data that you're binding to, well, you can safely say, or more safely say that this data is here, when the component is initialized. And so, this is where you'll put any kind of initialization code for your component into lifecycle hooks. So, what I'm gonna do here, reset selected course, drop this in, and we're going to save.
[00:10:41] And so, what we're essentially doing is resetting this to an emptyCourse to initialize it. So, if I go back here and select this, now we have Angular 9 Fundamentals. Let me just refresh this, make sure I am not throwing any errors in the code. So, we are looking good, and the reason is I'm no longer binding to a null, or property on a null object.
[00:11:08] Instead, I am initializing this to an empty component. And what we can do here, is. I'm going to create. A cancel method. And we'll just go this resetSelectedCourse, all right? So, within this method when it's hit, it's just going to reset. So, if I go back to my courses component here, let me put in button, and we're just going to go cancel, or rather to it like this.
[00:12:00] And then, we'll go, we'll set this to type button, we'll flesh this out a bit more in just a moment, but. Mat-button. So, this is snake hiss I hope, if not, zoom I see you. And, we'll go click, and we'll go cancel, right? Let's check this in. See, so there we go, select, cancel.
[00:12:37] It just sets it back to nothing. All right. So now, let's talk about this local template variable that we created, now that we have a form to actually work with, and see what this is doing. We'll, look at this form reference that we created. And we'll just kind of see what is happening here, like what is the stone.
[00:13:09] So, if I go under the card, let me see here, I think I can actually just put it in here, maybe not, but we'll try and we'll just dump this out. So, we're just going to go pre and we're going to go form.value. We'll go json. Let me duplicate that, and let me go form.valid, all right?
[00:13:46] Let's see if this renders. All right. Now, as I said, template reference or form reference is, you're not only keeping track of the value of the form, but is it valid? So now, if I type in title, you can see that I'm tracking the value of the entire form.
[00:14:11] And, if I go back, and right now I don't have any indication whether it's valid or not. So, if I go here and I go required, now, if there's nothing there, the form is in an invalid state. So now, you'll see, is it valid? No, it's not. And so, the minute I start typing, then it goes to true.
[00:14:35] And so, then it's now valid. And here are, or here is the value of the form. So, if I come back into the code, let me just duplicate this real quick. And, let's go with description. And, or let's actually, just because this is a placeholder, we will make title required, we'll make description optional.
[00:15:11] So, I actually did that backwards. So, back to the app. Now, you'll see, because I have added an additional entry model, that is attached to the entire form control. So, is it valid? No. Is it valid now? Yes, if I go cancel, it's no longer valid. So, as I start to type this in, now it's valid.
[00:15:37] If I remove the title, it's not only invalid, but you can see that the form control is surfacing some stuff for us to then check, is this an invalid state, yes or no? And then, we can essentially act upon that.