Building Awesomer Apps with Angular Building Awesomer Apps with Angular

Container and Presentational Components Demonstration

Check out a free preview of the full Building Awesomer Apps with Angular course:
The "Container and Presentational Components Demonstration" Lesson is part of the full, Building Awesomer Apps with Angular course featured in this preview video. Here's what you'd learn in this lesson:

Lukas reviews code demonstration the container and presentational components.

Get Unlimited Access Now

Transcript from the "Container and Presentational Components Demonstration" Lesson

[00:00:00]
>> Lukas Ruebbelke: So let me show you how this looks in the code. So we'll just walk through. I'll give you kind of a tour of what this looks like and then we'll break for lunch and get into our challenge.
>> Lukas Ruebbelke: So using the items component as our reference point.

[00:00:21] Because this actually has everything that I've talked about.
>> Lukas Ruebbelke: Let's look at first and foremost, the template. So there's very little layout happening here.
>> Lukas Ruebbelke: The only layout that is happening, really, is to put child components on the stage and kind of just arrange them appropriately. So you have the container and obviously I'm using the flexbox to kind of split them into two columns.

[00:00:56] Now if we look at this, we have an items list that has an input of items. And we know that this item can omit two events selected and deleted. Well that makes sense, you can select the event or select an item but you can also delete it. So now, when we select an item, what do you think happens?

[00:01:22] Is it set to two, current item. And so now, this is how that problem is solved. It's on the list. It's saying this was just selected. The list doesn't care. It just says hey, parent. Like this just what happened. Then, it sets current item and because it's now bound to the item detail.

[00:01:44] It's automatically going to update. And so, we know also that you can save or cancel. So we know on the detail component, you can save it, whatever's in there, or we can cancel it, we don't wanna do it. We don't need to do anything. So let's look at-

[00:02:01]
>> Lukas Ruebbelke: The item list component. So right here. No moving parts. It takes an input of an items array. I do have a property of read only. The reason being is if it's on the homepage I just want to read I don't want the ability for someone actually delete it from the homepage.

[00:02:24] And so, you can see here within the template this is, pretty much the rules of basic binding work. I'm just saying if it's not read only go ahead and show this button. If not, go ahead and hide it. So if reads only hide it, if it's not show it.

[00:02:43] But we're letting the parent define the context. And so if we go back to the items of this component, we're defaulting it to false, cause by default we wanna show it. But you can override that and say well no, we actually don't wanna show it, we want it to be read only in this context.

[00:03:01] So if we go to Home Component what do you think we're going to see? Well, before I get there, let's keep sharp here. We have an input of items. And read only. It also has an output of selected and deleted, so you can select an item or you can delete an item from the collection.

[00:03:25] Now if we jump over to the home component,
>> Lukas Ruebbelke: What do we have going on here? Outside of list, and we're only using the two inputs. We're saying, take these items, go ahead and render them. And we're setting this to read only. So in this context, we're letting the parent say, we want to display the item list but we want it to be read only.

[00:03:50] And then from here, it says great, I have items, and from here then in the template it just treats it any other property or method. Now the difference is with outputs, instead of calling the method, you do the output.emit. so you actually have to emit the event. So there's kinda that one thing you're dealing with event emitter.

[00:04:20] So when selected, or this button gets clicked it's called selected.omit or deleted.omit or passing up the item that we are deleting. But when I look at this, right here, I think this is absolutely incredible. We have a fully functional, non-trivial, component on the page. It is actually not doing anything other than rendering whatever you pass into it, and taking whatever user reaction happens to it, and kicking it back out.

[00:05:00] This is a very, very stable component.
>> Lukas Ruebbelke: Now for reference, let's also look at item detail.
>> Lukas Ruebbelke: So in item detail, we've obviously seen this a bit from using it as a reference point for the widget component.
>> Lukas Ruebbelke: The difference is, if we go into here, we have two outputs.

[00:05:29]
>> Lukas Ruebbelke: Saved and cancelled. And we have one input of item. So before I get into what's actually happening here, let's go back to our mark up. So it has one input of item. And it has a saved and a cancelled output. Now the question is, why pray tell, am I doing this right here?

[00:05:59] The reason being is, well, there's a famous quote. Not a famous quote, but there's this guy Venkat Subramaniam who has written a couple books on Groovy and he's just a pretty famous Groovy/Java programmer, really dynamic personality. And, it went over my head at the time, but. He was giving a talk in Phoenix.

[00:06:20] And he said, shared state is not a bad thing. Mutable state is not a bad thing. Share mutable state is the devil. In other words, when you have state that is shared between multiple components in any component can mutate that state. You have now put every other component that depends on that state at risk.

[00:06:51] And I'll talk a little bit more about that probably tomorrow. The point is, shared mutable state is a really good way for things to go horribly wrong in your application. So what do you do about forms? Obviously, at some point, somebody has to change state. You have to accept user input.

[00:07:11] And so this is something I really struggled with for a long time. And the simple answer is that you allow for the mutation to happen. By isolating the mutation. So you basically make it no longer shared. You simply say here's the state you're taking. It's potentially shared, lets go ahead and create a perimeter around it and isolate the state mutation until we're ready to save it, back up and persist it.

[00:07:43] So what I'm doing here is I've created an input but using ES 6 I've done a setter. So instead of doing it straight like this equals this every time I set item this method gets called. And from here I'm creating a local copy called by using Object.assign, so this is a handy way to create a copy of an object.

[00:08:07] So anytime we send an item, I am saying great. I have an item. Go ahead and create a copy of it and send it as selecteditem. Now, what I'm also doing here is I'm creating a reference to the originalName. The reason being is, you'll see here when I select this.

[00:08:34] If I was not binding to a reference to the original name here, the minute I started typing over this would start updating as well. So this is what I mean by shared mutable state. Let me ask you to just undo this. Look so I know kind of that you say shared mutable state and it's like!

[00:08:50] At least for me, the first time it went way over my head. So here.
>> Lukas Ruebbelke: So instead of binding to the stored reference, we'll go here.
>> Lukas Ruebbelke: This is what I mean by having shared mutable state. You change it here, in this field, and it's messing it up over here.

[00:09:16] And so it's a really benign example, but what if this was happening somewhere else in your application? And it was mutating C and you couldn't even see, like the fact is you can see this, it makes it a little easier to deal with, what happens is this changes something and you don't even know about it.

[00:09:31] Yey. Pass by reference. That's the nature of JavaScript, and really, most programming languages. And so that's why, for a UX experience, for just the user experience I store that off, but I also do it, so again I'm isolating that mutation.
>> Lukas Ruebbelke: So we'll set this back to its original name.

[00:09:53] So now when I select this, I can type it. And it's working on, essentially the copy that I created. So when I'm ready to save it. Then what I do is I simply say take this item that I've just changed, save it up, and pass it back. And so then we take that basically the cloned item, save it to the server, and we're good to go.

[00:10:18] But, I'll save it again, let's just put it back where it was. Let's say you just do something and you know like, eh, I didn't mean to do that, cancel. Well what does it do? It just throws away the clone, it doesn't need it because you haven't effected the original object.

[00:10:32] And so this is why the mutable operations are so important. For instance, as if you had an object with ten properties on it. And you started to change one property, then another, and then another. And then, you're, like, I actually need to undo this. I need to reset this object.

[00:10:53] I need to back it out. Well, how do you do that? We've already mutated the object. And what happens if you do property one, two, and five, and you need to mutate property two? Well now you gotta figure out how to actually step over with what you did on five, and go straight to two.

[00:11:08] It's a really hairy thing. Instead, as if you create a copy, I need to back this out, you just roll it back to the original copy. And so that is why in the item detail component I'm essentially creating a copy and I'm binding to it in the template.

[00:11:30] And so the form is bound to not item, but it is bound to selected item. Therefore my mutation is isolated to that component. And it can't escape until I save it out and emit that event.
>> Lukas Ruebbelke: Inputs, outputs.