Angular 9 Fundamentals Component API Input & Output
This course has been updated! We now recommend you take the Angular 13 Fundamentals course.
Transcript from the "Component API Input & Output" Lesson
>> And then what we need to do is I need to render some courses. But you know what? Let me go into my courses component or my course list component .Ts, and I'm just going to set this to an empty array for right now just so that we can see that it is rendering them back here.
[00:00:26] All right, so all I've done is I've created a new component, moved the template in. Now it'd be really great if I could get some courses in there to actually render. Well, you are in luck. So, we need to input or put the courses into the courses list component.
[00:00:53] We're going to do that via input, and so notice I've imported this input from Angular core, but remember if you're using a decorator like this, it is a method. And so if you just do input without the parentheses, it's going to be a problem. It's not going to work.
[00:01:16] So, I've also been bit by that. So we're gonna go courses and we'll just leave it here. So now, if I have an input of courses mean that I can put courses into this child component, how do I get them in there? Well, if I go to the courses list, watch this.
[00:01:48] It's picked up courses as an attribute. And so now I can say, this element that's bound to this component has a custom input called courses that I can then bind to as an attribute on the template. This, to me, is awesome. So, here, my goodness, lo and behold, I have now just taken the data from the parent component, passed it into the child component via an input.
[00:02:27] And let's take this a step further. So those DOM events that I removed. Now when somebody clicks on an element, I don't want to handle that in the child component. I want to delegate it up, and so it's like two small children, they get into a fight. That typically, one runs to mom, one runs to me and they're like, hey, so and so hit me and you need to take care of it.
[00:03:01] Similar thing here where it's this was selected, you do what you want with it, I don't care. I just wanna let you know that this happened. And so we signified these DOM events up to the parent component using outputs. And so if we go to the course list component, we can generate these custom events using output.
[00:03:27] And so notice I've imported this as well and I'm going to create an output event or an event called selected. And now what I have to do here is this is an event emitter. And so I need to instantiate it as an event emitter. So, I'm gonna show you something that is embarrassed me many, many times.
[00:03:54] Don't make this mistake. If you hit event emitter, and you get this auto import, notice it's coming from protractor. The reason being is event emitter apparently exists in more than one place. So let's try the next one. Well this is from events. I don't even know what that is.
[00:04:15] And so really be careful when you're using event emitter to get the event emitter from Angular core. This bit of information did not cost you anything, but it will save you a ton of pain down the road when you're like, I have this output, it should be working.
[00:04:35] I don't understand, event emitter. Then you realize you've imported it from somewhere else. So selected and deleted. Now what I can do is since I have these event emitters or these outputs, I can go back into my template. And what I can do now is I can convert this method call to selected, emit.
[00:05:02] And so now what I'm doing is I'm emitting that event up. I can go deleted dot emit. There we go. And so when somebody clicks, selected emit, and it's emitting that event for me to capture. Now, how do I handle this in the parent component? Well, I go to the courses component.html.
[00:05:33] And how do we bind to events? Well, if you remember, we put in these curly braces or actually parentheses and notice it picked up selected. Now on selected, what I can do is I can go select course and what I have to do here is. And this is just the way that Angular is, is when you're binding to an output, it has a single parameter, and that is this event object.
[00:06:11] And now, in your component class, you can call it whatever you want, but just in the template, it has to be event. Because I believe it's doing some mapping under the hood. I will do deleted, same thing, deleteCourse($event). So let's hop over and see if this worked. I think it did, but I really have no way of knowing.
[00:06:49] Well, what I could do is this, so let's go into AP course details. Well, let me do something real quick. Here, I don't need an event hook and I don't need a constructor. And so I want everybody to pay attention real quick to what is in this component class.
[00:07:27] I have one input and I have two outputs. This is a very, very thin component. And so this is what we would call a presentation component, where all this does is consume data via bindings. And then if something happens, like an event, it just delegates it back up.
[00:07:47] And so the question that I have, being that this is fully functional, How would you unit test this? Like, what logic in this component would you test? And the answer is, I personally would not unit test this component because there's no logic to test. Now, I would definitely end to end test it.
[00:08:17] But what you're doing is by using component driven architecture and creating these components that all they're doing is accepting input, emitting output. Without zero logic, they're delegating that backup. You create these ultra portable, ultra stable components. And so I would say this is the difference between like a platter hard drive versus a solid state hard drive.
[00:08:45] A platter hard drive, you slam the table and your heads skip and you can ruin the hard drive. A solid state, that doesn't happen. It's solid state. And so I see these as being equivalent of solid state hard drives in the component ecosystem. It's really hard to break these unless of course, Angular breaks or you put some bad data in.
[00:09:07] But assuming the data is correct, this is a very stable component. And so if we now go into our course details component, let's create an input. And so from here, input I'm just gonna call this course. Okay, from here, let me guess what I'm gonna do Course, of course I am.
[00:09:48] Gonna go to json, and then in our course component at HTML, I'm going to pass in, course. And from here, we're gonna do selectedCourse. Oops, selected course. Very good. Let's hop into the app and let's see if I broke something. Nope, I didn't break it. So let's step back into here.
[00:10:27] And let's do this just for fun. pre selectedCourse, and so now you can see like, I don't know if this even got in here. Let's just check. So go here. Back to here. That actually was working. I don't think it refreshed. So if I go here, save. There we go, no.
[00:10:57] Now what's interesting is this component, even though you can't see really visually, this component has no idea what's happening to this component over here. They are completely oblivious to each other. And this is also really, really important. So let's complete or let's move this entire thing into the appropriate template.
[00:11:39] What I'm gonna do is, It says selectedCourse, I'm going to just change this to course for a minute. Now, notice it's saying, I don't know what save course is, so I'm just gonna go save or save courses so I'm just gonna go saved. Actually, we'll do saved.emit. And down here, we're going to go cancel that emit.
[00:12:11] But those don't exist, but they will exist. So we're gonna go here. Output, and we're gonna go saved = new EventEmitter and Output canceled = new. That's what I did there. That's bad. That's how you get burnt cuz that would have broken that. So there we go. All right.
[00:13:02] And possibly, this may work. I hope it's canceled. Let me iron that up. I'm not seeing any red, I'm feeling pretty good about this. Let's give this a shot. So at least the form is rendering. Look at this. And if I go canceled, that didn't work because I haven't hooked up the output yet.
[00:13:33] So let's go back here into our course details component, or rather sorry, our course component and let's wire up these outputs. So we'll go here, and, saved. Save course and we're gonna do $event, just so we get the secret handshake correct. And we'll go canceled. We'll just do canceled, so you don't have to send a parameter through.
[00:14:30] All right, let's go back. Cancel, cancel, here, submit. Very good.