Check out a free preview of the full Building Awesome Web Apps with Angular 2 course:
The "Challenge 7: Solution, Part II" Lesson is part of the full, Building Awesome Web Apps with Angular 2 course featured in this preview video. Here's what you'd learn in this lesson:

Abstracting the templates, Lukas continues demonstrating the solution to Challenge 6 by creating the widget-details component.

Get Unlimited Access Now

Transcript from the "Challenge 7: Solution, Part II" Lesson

[00:00:00]
>> Lukas Ruebbelke: Now, that we have these alive and well in our application, what do you suppose the next step is?
>> Speaker 2: Abstract the templates.
>> Lukas Ruebbelke: Yeah, abstract the templates, very good. So, we know that we're here, everything is kinda hooked up properly. So, let's put the templates in. So, we'll go back here, and, yes, I see somebody saying Angular CLI scaffolding.

[00:00:30] I would just be a hypocrite if I just scolded everybody muscle memory, and then I scaffold it. All right, so I'm just gonna copy this. And we'll go to.
>> Lukas Ruebbelke: Widget Detail component. And I'm going to paste this here. Let's go back to a widget component. And I fully expect that when we run this, this is going to break.

[00:01:08]
>> Lukas Ruebbelke: So, we'll chop this and.
>> Lukas Ruebbelke: Widget, list, component, yeah.
>> Lukas Ruebbelke: Okay.
>> Lukas Ruebbelke: So, kinda works? But see, I'm not throwing any air, so that's a good sign.
>> Lukas Ruebbelke: So, now, what we need to do is first things first, we need to get widgets into our widgets list.

[00:02:01] So, what would we use for that?
>> Speaker 3: Input.
>> Lukas Ruebbelke: Input, yes, very good. And so, now, let's start with the list component here, and let's just call it widgets.
>> Lukas Ruebbelke: And.
>> Lukas Ruebbelke: Say this is an array of widgets.
>> Lukas Ruebbelke: Come on. There we go. And so, now, I'm saying, I have an input of widgets that I'm going to get from my parent component.

[00:02:45] Now, if we go here to. Let's close this down.
>> Lukas Ruebbelke: [widgets] ="widgets". Now, we just verified that if I go to the widgets component. Yes, we do indeed have the widgets properly on the parent. I'm essentially taking this property, and more so its value, and were passing it into the widgets list component.

[00:03:20] So far so good?
>> Lukas Ruebbelke: Super, there it is. Now, I feel like. Let me see here. Okay, I'm messing up on the CSS somewhere, but I'm not going to worry about that just yet. So, now, what we need to do is, more importantly, we need to capture the click event when we select a widget's item from the list, and service it back up to our widget's component.

[00:04:19] So, let's go into here.
>> Lukas Ruebbelke: And let's call this output selected, now, this is a new event emitter.
>> Lukas Ruebbelke: And.
>> Lukas Ruebbelke: We're going to define this as output.
>> Lukas Ruebbelke: Did this not import, come on.
>> Lukas Ruebbelke: Ha!
>> Speaker 4: Make sure you pick the right one, there's six of them.

[00:04:57]
>> Lukas Ruebbelke: Yeah, exactly let's see here, which one do I have?
>> Speaker 5: Put Output EventEmitter you're missing.
>> Lukas Ruebbelke: Let's just take one from the core, okay? And then we'll go back to our component here, and select it.
>> Lukas Ruebbelke: Select widget. Rather, that's what I want. So, now, we need to trigger this from our list component.

[00:05:45]
>> Lukas Ruebbelke: selected.emit.
>> Lukas Ruebbelke: And let's see here.
>> Lukas Ruebbelke: Let's hop back in.
>> Lukas Ruebbelke: Click, selected, a MIT widget. Let's go back here.
>> Lukas Ruebbelke: selected, selectWidget.
>> Lukas Ruebbelke: Just make sure this is firing.
>> Lukas Ruebbelke: Okay, good, so this is actually what I want, but I haven't hooked up the input. For my widget details component.

[00:06:50] Duh.
>> Lukas Ruebbelke: I totally thought about something.
>> Lukas Ruebbelke: Okay, and so now, in our widget deep div component, we have selected widget.
>> Lukas Ruebbelke: Let me just rename this real quick, just gonna call this widget, widget, widget.
>> Lukas Ruebbelke: There we go, and in our detail component, let's go input.
>> Lukas Ruebbelke: So, now, we have the input, and what do we need to do here to get our selected widget?

[00:07:49] Into our widget detail component. Yep. So, it is property binding. ="selectedWidget".
>> Lukas Ruebbelke: So now you can see here, we're just using inputs, outputs. And we're saying, now take the selected widget and put it in here.
>> Lukas Ruebbelke: Okay, refresh the page.
>> Lukas Ruebbelke: And here we go. So styling aside, this is pretty much what we want to happen.

[00:08:35]
>> Lukas Ruebbelke: What else did I say in here?
>> Lukas Ruebbelke: So delete, save, and cancel. So let's wire those up real quick.
>> Lukas Ruebbelke: So if we go to our items,
>> Lukas Ruebbelke: Or item list, rather.
>> Lukas Ruebbelke: There it is. You just copy this.
>> Lukas Ruebbelke: And we'll go to our,
>> Lukas Ruebbelke: Widget list component or rather HTML.

[00:09:29]
>> Lukas Ruebbelke: And so here, we've already kind of predefined this deleted, so let's go into the component.
>> Lukas Ruebbelke: Deleted = new EventEmitter. And then what we'll do is in the widget component itself, well actually first we need to hook this up.
>> Lukas Ruebbelke: Delete it, we'll go deleteWidget event, and then we will hook this up in the component.

[00:10:21]
>> Lukas Ruebbelke: So we have selectWidget, just make sure I don't. Okay, so from here.
>> Lukas Ruebbelke: Delete the widget.
>> Lukas Ruebbelke: Okay?
>> Lukas Ruebbelke: And let me make sure. I think this is everything, let's see.
>> Speaker 6: I think you copied and pasted an item in there. Should it be widget for your delete?

[00:10:58]
>> Lukas Ruebbelke: Did I, yeah, I think you are correct. Did I do this in?
>> Speaker 6: Your list component HTML, on the left.
>> Lukas Ruebbelke: On the left.
>> Speaker 6: I'm looking at your tabs up on the left there.
>> Lukas Ruebbelke: Right here.
>> Speaker 6: Yeah, there deleted.emit.
>> Lukas Ruebbelke: You are my true homey.

[00:11:25]
>> Lukas Ruebbelke: Mark give this guy a cookie when we go on break after this.
>> Speaker 7: There's a whole stack of cookies next right next to him.
>> Lukas Ruebbelke: There we go so now we are surfacing this item for deletion.
>> Lukas Ruebbelke: And two more and then we actually will take a break cuz this is exhausted, all this live coding.

[00:11:54]
>> Lukas Ruebbelke: Let's go back into our code and,
>> Lukas Ruebbelke: Item detail HTML.
>> Lukas Ruebbelke: Just copy this.
>> Lukas Ruebbelke: Let's get this out of here.
>> Lukas Ruebbelke: Widget I'm gonna leave this here, we'll get into this next. Widget and actually I know what is happening here and we'll talk about this in the next episode.

[00:12:39] Okay two outputs.
>> Lukas Ruebbelke: Widget detail component.
>> Lukas Ruebbelke: Boom. Okay, was it saved? EventEmitter.
>> Lukas Ruebbelke: And cancel. Did I do that right? Let me check. Cancelled saved. Saved cancelled. And so from here,
>> Lukas Ruebbelke: We are in the home stretch.
>> Lukas Ruebbelke: Event.
>> Lukas Ruebbelke: Does this look ok? I think, it feels right in my soul.

[00:14:52] I feel like I've made good choices with my life.
>> Lukas Ruebbelke: So that's working. Yay. All right.
>> Lukas Ruebbelke: And there we go.
>> Lukas Ruebbelke: So any questions about what I've done in this example.
>> Lukas Ruebbelke: I think the most important thing that I wanna call out is, when we look at our widgets component, does this right here and right here, does this make sense?

[00:15:47]
>> Speaker 8: So just to clarify for my own sake, essentially the input and the output, there on the left where in brackets or parens is kind of what it's referenced as in the child. Right?
>> Lukas Ruebbelke: Mm-hm.
>> Speaker 8: Whereas in the quotes is what it's used in the parent, that's kind of how the parent is handling it?

[00:16:05]
>> Lukas Ruebbelke: So what happens is the child is responsible for defining its interface. So let's see if I can do, let me just see if I can pick one of these here.
>> Lukas Ruebbelke: Let's go with.
>> Lukas Ruebbelke: All right, we'll do this one.
>> Lukas Ruebbelke: So we can see here.
>> Lukas Ruebbelke: So in the widget detail component.

[00:16:43]
>> Lukas Ruebbelke: Hold on, somebody just made something totally funny.
>> Lukas Ruebbelke: Somebody said Less CSS would be easier and somebody's like Less, like capital L-E-S-S or Less. That's-
>> Speaker 4: They're being sassy.
>> Lukas Ruebbelke: That's aw. You just totally, say it, put it in there.
>> All: [LAUGH]
>> Speaker 4: They all heard it.

[00:17:06]
>> Lukas Ruebbelke: Yeah. All right, so, back on track here. I'm gonna be laughing about that all afternoon. In our WidgetDetail component, i.e., the child component,
>> Lukas Ruebbelke: We have defined essentially, our interface, our inputs and outputs. And over here, in the parent component, we are now leveraging our inputs and outputs, to interact with the child component.

[00:17:41] Does that make sense? And so again, I want everybody to think of inputs and outputs are really just custom properties and events that we're defining for our child component.
>> Lukas Ruebbelke: And that is really at the core,
>> Lukas Ruebbelke: What we're doing here? We're simply saying, I'm creating a custom component and I want to set these properties on it.

[00:18:08] And I want it, when something happens to them at these events, so I can handle them outside of the component.
>> Lukas Ruebbelke: Yes?
>> Speaker 5: I had a question on the event.stop propagation on the button, on the click event. What exactly does that do?
>> Lukas Ruebbelke: So what happens is because you have a child button or really that delete button, that sits on top of another element that we're also listening for a click event, is that event was triggering both of them.

[00:18:48] So what I'm saying is when I click the delete button, I want to stop the click event entirely. Instead of letting it basically bubble through my DOM. So essentially it's like hey, stop the event, essentially it's a delete button and do not let it go any further.
>> Speaker 5: It would've triggered like the select event for attempting to?

[00:19:08]
>> Lukas Ruebbelke: Mm-hm, yep, and so basically DOM events will bubble.
>> Speaker 5: Okay.
>> Lukas Ruebbelke: And that's what I wanted to prevent. So using event.stop propagation, you simply say stop it here and, allow it to go no further.
>> Lukas Ruebbelke: Because there are, sometimes in a DOM, where you click on something, but there might be text or something when you really actually want to click the underlying element or the group of elements.

[00:19:31] And so, it's really the question is where is that DOM event targeting. And so sometimes letting a bubble is good, that's exactly what you want. Other times you wanna just isolate it to just that event. So Chris P had a question I'm just gonna address real quick. And that is, does ngOnInit execute after input is passed in?

[00:19:56]
>> Lukas Ruebbelke: And the answer is yes, afterwards. So if you go to day one slides and you look at the life cycle of hooks, slide in particular that ngOnInit is called after the first ngOnChanges. Well, this gets called, ngOnChanges gets called when an input or output binding value changes.

[00:20:24] So essentially you have to have an input or an output. In this case, an input, once it changes at least once, it's been initialized, then ngOnInit gets called. So in a nutshell, what I've always just said is ngOnInit happens after the bindings have been initialized. And so, now you can see from the documentation is that it's called after the first ngOnChanges, at which point you can safely assume that,

[00:20:53]
>> Lukas Ruebbelke: Essentially, your bindings are there, your input has been satisfied and the binding is ready to go.