3.1 Creating a QuizList Component
One of the fundamental building blocks of Vue.js is the component. Think of components as self-contained functionality that includes HTML templates, corresponding scripts and logic, and any necessary styling. Let's begin exploring components and see how to create them.
1.Introduction3 lessons, 18:29
2.Vue.js Basics3 lessons, 18:35
3.Coding the Quiz Components7 lessons, 1:00:56
4.Transitions and Finishing Touches4 lessons, 38:45
5.Conclusion1 lesson, 02:17
3.1 Creating a QuizList Component
So far our app is coming along nicely, and we've learned a little bit about string interpolation and presenting data to the end user. And then looping through elements and creating multiple instances of those elements on our DOM, on our page, so that we can loop through collections like we did for the quizzes so far. Now all these things are really good, but this is a good point for us to kind of take a step back and realize what is going to happen very quickly. As we begin to add more elements to our template and begin to add additional functionality and things like that. We're quickly going to start to get a lot of things going on in our App.vue file, which we really wanna consider kind of like the highest level of our application. And we really want to kind of create this as an entry point where we're going to begin the view of our application, where we're going to begin the creation of our UI. What we really don't want to happen here is to have a lot of bloats, where we're starting to create lots of elements. Where we're creating lots of nesting and things like that, where this file becomes very large. Because it then becomes very difficult for us to make changes to this or reuse components. Now we have to copy and paste large blocks of HTML into different places of our application. One very cool solution to this problem is to simply create a new component. So that's what we are going to look at in this lesson. So what I want to do now is, I want to take this work that we've done for creating what I'm going to call a quiz list, which is basically what this is. And extract that into its own component so that we could re-use it in different places of our application, should we ever choose to use it somewhere else. So let's see what the process looks like in order to create a new component. So what I'm gonna do, is I'm gonna come over to my component's folder here and I'm going to create a new file. And let's just go ahead and call this Quizlist.view, but you can call it anything that you want, but Quizlist, I think, is representative of what we want to do here. So go ahead and create that, and I'm just going to let Atom know that this is an HTML file, just so that we get some syntax highlighting. Then let's go ahead and create the three main sections that are crucial to our components. So once again, we are going to have a template. So we'll go ahead and create that section right here. And then down below we're going to have a script section, so we'll go ahead and create that, and then finally we are going to have a style section. Now these are just basically the three main sections that we're gonna have when it comes to these components. So it usually pays to create them up front. So basically what I wanna be able to do now is I wanna be able to create this new component and have it be a QuizList. And have it be a QuizList that I can use in different places. So let's begin by coming over to our app.vue, and let's simply take this div out of here. And we'll simply copy this, and we'll stick it over here as our template in QuizList. So that's the first basic part of this, so let's go ahead and save this. The next thing that I'm gonna wanna do is create my module that's going to get exported here. So I'm gonna say export default, and then within here is where we're gonna begin to export some things that we can make accessible to the rest of our component and, especially, our template. Now the first thing that's gonna become very obvious very quickly is, if I come back to this new QuizList and I take a look at my template. We have this v for loop right here where I'm looping through this concept of quizzes. But to this point, we don't have anything in this component that really defines quizzes. Cuz remember what I said, once we start to create these single file components, they are really self-contained. And in order for all of this to work, we have to be able to define these things within this component. Well, the problem is right now quizzes is actually defined in app.vue in this data section. So how do we access to this data right here as quizzes in our new QuizList.view component? Well, the way that we do that is by exposing a property outside of this component to rest of the world that we can bind to. And the way that we do that is, within our export here, we can create a property called props. And props is going to be a list of string names that we can use to bind data to it or to pass data in to this particular component. And what we're gonna do here is we're going to define a property called Quizzes. So that's the first step in being able to define this concept of quizzes within my template and be able to use it within my component. So this, in essence, is going to define a property that's going to be accessible within this component. But right now, there's nothing in it, it's basically empty. So how do we actually pass data into it? Well, we're going to start by coming over to our App.vue and say, all right, so now I no longer have this concept of all of this markup right here. I've actually taken all of this out and I've stuck it into the QuizList. Or actually, better than that, I should be taking inside the div, so instead of actually copying at this point, I'm actually going to cut this out. And I'm gonna come over to my QuizList and this is going to be my template. And I wanna leave my kind of parent ID over in App.vue. Okay, so now what I wanna do is, I want to use this new component that I'm creating. And I can use this as an element, as you saw earlier when we were taking a look at this Hello.vue when it was being referenced in App.vue. So the cool thing about this now is, when I create a new component, I now have the ability to reference that component in other components. And I can use it as an element all throughout my application, so how does that work? So we are using this QuizList.view template or component, I can reference that in my App.vue by doing two things. The first thing that I have to do is I have to import it. So I have to import QuizList from, and I have to specify where this is coming from, with the location that I can find it in a relative path. So currently I am in the source folder in the App.vue file. I need to go into components and get access to QuizList. So I simply say ./components/, and I can simply refer to this as QuizList, and I can leave the vue off the end of that. I don't need to add that extension onto it. Okay, so that's step one. Step two is I have to reference this new component within the components section of my module. So I'm gonna say here that I am going to use the QuizList component. Now I'm able to use that QuizList component within this parent component simply by referring to it as an html element. Now there are a couple rules around this, now depending how you name these elements, you might have to do some special naming of your element within here. So in most instances, if it's a single named component where if I just were to call this quiz, I could create an element here and I could call that element quiz. But because I called it QuizList, it's two words denoted by the capital letters, I can say quiz-list. So basically anywhere where you're denoting the different words in your component with capital letters, I now have to divide that up with a hyphen. So now I can create this element called Quiz-List, just like this. Simply by the fact that I've created a new component called QuizList, then I can reference it by importing it from wherever I want. Reference that component in the components section of my module, and then I can refer to it as an element within this template. Let's go ahead and save these changes, let's come back over here and we're gonna see now that we have an error. And so here we see the first problem. Now this is something to remember when you are working with components and templates all throughout vue. And the important line to take a look at is right here at the bottom. We cannot use v-for on stateful component root element, because it renders multiple elements. So basically what this is telling us is that, within our quiz-list we have this v-for, but this v-for is modifying or is creating multiple instances of this root element. So the first thing we need to do is, we need to wrap this entire thing in another element. So we can't have a v-for running in an element that is the root. So let's go ahead and copy or cut and paste this into a parent div like this, let's go ahead and save that. And now we'll come back, and let's just clear out this console and we'll refresh. And everything seems to work, but I'm not getting anything, I'm not getting any errors, but I'm not getting any data. All right, so the next thing that we need to do is, now that we are able to have this QuizList components run all by itself, I need to be able to pass data into it. And the way that I'm gonna do that is I'm going to take this quizzes data that I have here, and I wanna pass it into this QuizList component so that it's assigned to this quizzes property. And the way that we do that is by binding. And we're going to use another special element in here, we're going to say v-bind. And then we're going to use a colon here and we're gonna say what property do we want to bind to? And that property always has to be defined within this props collection within the target module. And then within here I can say I want to bind:quizzes, and what do I wanna bind to that? I wanna bind this quizzes object right here. So I'm going to go ahead and say quizzes. Now it's important to note here that, when you are assigning information or assigning data within an attribute, you don't have to use the curly brackets. And actually you are not supposed to use the curly brackets. So if I were to add them in here and hit save, I'm gonna come over here and I'm going to get an error because there's an invalid expression. I have these curly brackets in here and it doesn't like that. So let's come back over here and let's go ahead and remove those curly brackets, go ahead and hit save. And if I come back over here, now my component is being displayed properly again. So let's review quickly what we've done here. We quickly notice that if we continue to add information about this list of quizzes to our App.vue file and we started to tweak things. Things were gonna get very large and out of hand very quickly. So we made the executive decision to take that reusable component, this idea of a QuizList, and extract it into its own component with its own template, and its own exporting and making available a property called quizzes. And by doing that, I was now able to come back over to the initial view, my app.vue that I started in. I was able to import this new QuizList component from its location. I then referenced it within my components collection, and then I was able to use that component as an element inside of this new parent view. And then I could get access to the properties that I defined within that component by using this v-bind syntax, where we're binding to a particular property on the QuizList component. And then I'm passing in a piece of data, in this case, quizzes, that I have access to right here. So this is a very important process to understand how to create components and how to get data into it throughout the lifecycle of your application.