Restore boilerplate and goal0:34
You'll look at it and go, I have no clue what all of this stuff is. So that's why I wanted to introduce you to the concept very early in your learning. And trust me, if you can get comfortable with this, you're going to be unstoppable. So with all of that said, let's bring it all together in this episode. All right, so have a look at index.html. You can see I've reverted everything back to our initial beginning boilerplate, which means if I view this in the browser, we of course get a blank page. Okay, so now I want to bring your attention back to the basic assignments list that we worked on a few episodes ago. Now I want to take everything we learned about Vue components and apply it to something as
Move template into app.js1:08
worked on a few episodes ago. Now I want to take everything we learned about Vue components and apply it to something as simple as this. Okay, it sounds like the first step, and we're going to do this incrementally. Sounds like the first step is to select everything here, cut that out, and I'm going to move it into app.js. Now a quick little note, sometimes it might feel gross to store all of this HTML as a JavaScript property value, and I can sympathize with that. Just keep in mind though, a little further along in your learning, I will introduce something known as single file components, and that solves this problem entirely.
Just keep in mind though, a little further along in your learning, I will introduce something known as single file components, and that solves this problem entirely. So just stay tuned a little bit longer. Okay, so now app.js has a template for all of our assignments. And notice we're referencing all of these things that need to exist, but right now, they don't. Okay, that's the next step. Let's return to backup.html, and I'm going to select the data method and those computed properties, and I will migrate that here. Okay, so I think that's everything.
properties, and I will migrate that here. Okay, so I think that's everything. I can delete backup.html, and now let's quickly go through what's going on. In our script, we import our root component, and then we mount it to this div here. Our root component consists of this template here, where we have two sections that represent our assignments list. So with any luck, if I come back and refresh the page, there we go. We once again see our basic assignments. It works. Okay, so now I want to think in terms of view components, and let's break it down.
Plan component breakdown2:45
It works. Okay, so now I want to think in terms of view components, and let's break it down. Let's do this together. If we were to take a look at this, what do we have here? I might say, well, these two are assignments, right? This represents our assignments section or our assignments component. And then within it, I can see two sections. There's one, and there's another. They're basically the same thing. Those are, and fill in the blank, those are assignment lists.
And each of those lists consists of any number of single assignments. That would be a decent way to componentize, if that's a word. I don't think it is. To componentize this section here. So let's see if we can make that a reality. Let's create those components that I mentioned. One of them was called Assignments. That's like the outer wrapper. Another one was our AssignmentList. So do you want that to be plural or singular?
Extract Assignments component4:03
Another one was our assignment list. So do you want that to be plural or singular? AssignmentsList? Be singular. And then finally, we have our single assignment. All right, let's get to work. The first step, why don't we start with the outer shell? And again, that represents everything you see here. Okay. So in app.js, well, it looks like once again, I'm moving both of these sections to their
Okay. So in app.js, well, it looks like once again, I'm moving both of these sections to their new home in assignments.js. Like this. All right, looks good. Next we need to provide the data. So once again, we're moving these things around twice, but that's okay. Paste it in down here at the bottom. Okay. So now if nothing else, we have a new home for all of our assignments, and that home
Okay. So now if nothing else, we have a new home for all of our assignments, and that home is called assignments. It just makes sense. But yeah, now if I switch back to app.js, it's blank, which means if I refresh the page, I don't see anything. Okay. So let's pull in our component. Import assignments from assignments.js. Remember if we want to use it, well actually, let's just see what happens.
Import assignments from assignments.js. Remember if we want to use it, well actually, let's just see what happens. If I try to use assignments like this, it's not going to work. Come back, refresh, and you'll see in the console, we should have, there we go, a warning. Failed to resolve component assignments. So we're trying to reference a view component, but we haven't registered it. So you register it by adding that components property that you learned about. And actually in future episodes, once you start learning about single file components, you'll then be able to create your tags like this, but we can't do that just yet. Okay.
you'll then be able to create your tags like this, but we can't do that just yet. Okay. So come back, refresh the page, and with any luck, there we go. I can see our assignments. Okay. So we're starting to make a little bit of progress. I like this. What can we do next? Well, in assignments.js, we have two lists. So why don't we begin migrating those to our new component, AssignmentList.
Create reusable AssignmentList6:02
Well, in assignments.js, we have two lists. So why don't we begin migrating those to our new component, AssignmentList? Exact same system here. Add our template and paste in the markup for an assignment list. And now for this component to work, let's see, it needs to have a collection of assignments, it needs to have a title, and then it loops over that collection and displays the data. Okay. So for this to work, it needs to be given a collection of assignments. So that would be an array. I said collection, so it should be an array.
So that would be an array. I said collection, so it should be an array. So basically what I'm doing here is I'm removing all specifics. And we'll do the same thing for title, by the way. I don't want to hard code anything like inProgress because then this component is linked to inProgress assignments, and I don't want that. It can be linked to any kind of assignment list. Okay. So let's update this to title. And then I'm going to remove any references to inProgress assignments.
So let's update this to title. And then I'm going to remove any references to inProgressAssignments. That will now simply be assignments. Okay. And I think that's looking pretty good. So if I now switch back, let's comment out this and replace it with our new component. Import AssignmentList from assignmentlist.js, and then exact same system. Register it as a component. And now we can use it in our template. AssignmentList.
And now we can use it in our template. Assignment list. But now, don't forget, in order for this component to do its job, it needs these two things. So let's pass those in as props. We need our assignments, and we need a title. Okay. So this first one will be in progress assignments. So I will pass this in, but don't forget, if we do it like this, we're passing in the string in progress assignments. I don't want that.
string in progress assignments. I don't want that. I want the value associated with that data property or that computed property. So I will use v-bind or the shorthand :. Next for the title, I'm happy for this to be a string. So I don't need to bind that to anything. Cool. So let's cross our fingers. Does this work? And it looks like it does.
assignment list. And it looks like this one is for completed assignments. So I'll paste that in and update the title. Yeah, so notice we made AssignmentList generic, which means we can pass in data from the outside to configure it. So now get rid of all of this, and look how much cleaner this is looking. Come back, give it a refresh, and this is working. But now notice I have two AssignmentList components. Okay, now we move on to the final step. Within our AssignmentList, we need to extract what we see here.
Extract single Assignment component10:11
But now notice we are looping over many assignments, but that doesn't make sense. This component should be the markup for one assignment. So I'm going to remove all of that, and we will instead store that on the outside, like this. Come back to assignments list, and now, yeah, we're going to do something like assignment, and then here I could paste in that V4. And let's clean this up, like that. Okay, we'll come back to this in a second, but let's finish up over here. So now for this component to do its job, it looks like it only needs an assignment object. All right, props, assignment object, and that should do it.
I get the white screen death. I was getting a little too cocky there, so that was probably good for me. Let's see what the problem is. I go to the console, and we have an error, cannot read property of undefined, it was trying to read name. Okay, so it looks like the issue was in our Assignment component, it's trying to read name here, but for some reason, assignment is undefined rather than an object. So what I would do is I would check, okay, well, am I passing in an assignment when I call this component? Let's see.
UI spacing and cleanup12:36
First up, we need a little bit of spacing there. So if I switch back to all of our assignments, here's what we could do. I'm going to wrap all of this within maybe a section, like so, and then because I'm using Tailwind, there's actually a space-y class I can use that will add a certain amount of space between each of the direct children. So if I come back and refresh, this should work, and yeah, if you're curious at all, you can see here's what it's doing. It will find the next sibling of any element that's not hidden, and add the necessary margin-top and margin-bottom, and yeah, that's an easy way to solve the problem. Okay, so my final bit of cleanup is back in my AssignmentsComponent, if we scroll down,
top and margin bottom, and yeah, that's an easy way to solve the problem. Okay, so my final bit of cleanup is back in my Assignments component, if we scroll down, we have these computed properties, and these names are a little verbose. They were verbose because originally we had them within a single index.html file that wasn't linked to Assignments, which means we could have had reactive data associated with the User, or theme, or settings, or other areas of the page that weren't exclusive to Assignments. But now everything related to Assignments is stored here, which means I can simplify things drastically. Do I really need to call this inProgressAssignments?
Refactor computed filters14:21
So if down the line we want to introduce a new way to filter assignments, like give me the ones that are oldest, well right now I would need to create another computed property, right? Or what if we did this instead? What if I just have a computed property called filters, and this could contain an object of any number of filters that we provide, including inProgress and completed. So that would look like this, because really these are just simple little operations, so I don't have a problem storing them together. So I'll move all of this. And yeah, if a few months from now we want to add another filter, it's as easy as adding
