Project Overview: Nesting Multiple Components
Hey, what's going on gang? Welcome to your 21st Vue.js tutorial. In this video, I want to give you some more examples of how we can nest components. Okay, so in the last tutorial, I showed you how we could nest a component in the root component. So in this tutorial, I want to take it one step further and just create a few extra components and nest them all.
Okay, so essentially what we're going to do is create a simple web page with some different components controlling the different sections of that web page. So we're going to have our root component sitting at the top as always, then underneath, three components: one for the header with a title in it, one for the footer with a copyright notice in, and then one for the main content called the Ninja component, which is going to be a list of ninjas and their special abilities.
Okay, so I've stripped out all the content from our previous tutorial. We no longer have that Ninja view file right here. We just have the app.vue, the main root component, and it's pretty empty at the minute.
So what I want to do first of all is create our other three components: the header, footer, and the ninja component. And then we're going to import them into this root component and nest them in here in the template. So let's go to this Source folder and create our new components.
First of all, I'm going to create a new folder just to keep everything kind of logically stored together. And this folder is going to be called components. So all of our three components are going to live in here now. Okay, so I'm going to create a new file and this one is going to be called header.vue. And in here, what I want to do is create the header component. So first of all, I'm just going to copy this because it's just a blank component basically, and paste it in here.
So we need to create our template for the header, and I'm going to keep this really simple. So it is literally going to have a header tag, and then inside the header tag, it's going to have an h1. And we're going to dynamically output that h1 using a data property down here called 'title'. So let's create that property, title, and then this is going to be called View Ninjas. So this is the header component, which is just basically a title.
Now, I am going to give this some styles, so I'll come down here and they are going to be scoped. Remember, we use scoped to say I only want these styles to apply to this component. So we want to style up the header first of all. And this header is going to have a background of light green. And then I'm also going to give this header a padding all the way around of around 10 pixels. Then I also want to style this h1 right here as well. So we'll say h1, and this is going to have a color of kind of like a dark gray, which is #222. That's a hex code for dark gray. And it's going to be text-align to the center, so it sits in the middle.
Importing and Nesting the Header
Okay, so we've created our header component right there. So what we'll do now is import this header component into the root component right there and then nest it in it. So remember, we can do that by coming to this script tag down here and first of all saying import, and then we want to say what we want to import and where from. Now we want to import the header component over here in the components folder. Right? So we need to say import Header from './components/header.vue'. Okay, so we're importing that.
Now we need to list or register this component in the root component to say, yeah, we can use it in this component. So remember, the way we do that is by saying components and then this is an object and we can list our components here. So what we're going to call this one is app-header, and I'll tell you the reason I'm doing that in a second. And this is going to be the Header, so this thing right here. So when we create a tag up here, it's going to be this in the tag, because this is the name.
Now why did I not just use header? Well, the reason is this is already a tag, an HTML tag, so I can't just do header because that's already an HTML tag and Vue.js won't like that. So I'm going to have to do it something different, and that is the reason I placed app- in front of it. Okay, so let's pop a comment at the end of that object as well. So now we've registered this app-header component here in the component rather, so we can add it to the template, we can nest it in here.
So first of all, I want a div tag to surround everything within this template. And then we're going to nest that component. So I'll say <app-header> to nest that right there. And if we save this now and view it in a browser, then we should see that header at the top. Cool. Okay, so there's one out of three components.
Now I want to move on to the footer component. So again, I'm going to create this file in the components folder. New file, and we'll call this footer.vue. And inside here, we want to paste this thing again. So we'll copy it and paste it inside the footer one. We just need to delete a couple of things like this. And we don't want to import that. We just want an empty component here basically. Okay, cool. So now we can do our template for the footer, which is just going to be <footer>, an HTML5 tag. Then inside the footer, I want some kind of copyright notice. So I'll give a P tag and then we'll output this dynamically and we'll call this copyright.
Okay, so now we need to define this property down here on the object. So we'll come down here and say copyright, and this is just going to be a string and it says Copyright 2000 View Ninjas. Okay, something like that. All right. So now we have this defined. We want to just style up the foot a little bit. So we'll come down here and we'll say style is going to be scoped, just to apply the styles to this component. And underneath we'll say footer, and we want this to have a background of dark gray again. So we'll use the hex code of #222 to do that. We also want to give this a bit of a padding, about six pixels all the way around. I want to style this P tag as well. So we'll say p, and this is also going to have a color of light green, and then we'll text-align this to the center as well. Okay.
So now we've created our footer component as well. Let's import that into the app.vue, the root component, and place it below the header. So again, we need to add this component, we need to register it here to say that we can nest it up here in this root component. So we'll call this one app-footer for the same reason. We can't just use footer because this is already an HTML5 tag. So this is going to be Footer, which we're going to import right now. So let's copy this and paste it down below, and this time we'll say Footer and this is going to be importing from the components folder, footer.vue file. Okay, so now we can add it below here. So we'll say <app-footer> to nest that. Save it and check this out in the browser. And now we have the footer as well. Cool.
Building the Dynamic "Ninjas" List Component
So this is all going perfectly. Now we just need to get our main content between the header and the footer. So we want to be placing our other component right here. Okay, so let's create that component then. I'm going to place this in the components folder again. We'll call this a new file, ninjas.vue. And then we'll just copy one of these things here and paste it in because I'm super lazy. And get rid of that stuff, get rid of this data, and also this styling.
Okay, so this is going to be the most complex component, but still, we're not going to cover anything we've not learned so far. So basically, I want this component to be some kind of grid of ninjas. And each ninja is going to be like a box in this grid or a panel in this grid. And when you click on one of the ninjas, it's going to show the special ability of that ninja, right? So first thing we want is some data for these ninjas. Now, I've already copied this to my clipboard and you can get it from the GitHub repo, the link is down below, Lesson 21 you want. And I'm going to paste this data right here. So it's a property called ninjas and this is an array, and this array holds what, about six objects. And each object is a ninja and it has a name, specialty, and then this show property. And it's currently set to false for each one. Now when this is false, the ninja's not going to show the specialty, but when it is true, the ninja will show that specialty. And it's going to toggle this show property when we click on that ninja. So when we click it, it's going to turn to true. When we click it again, it's going to turn to false. Okay, so pretty simple.
So now what we want to do is cycle through these ninjas up here in the template and we want to output them, right? We want to show them in the main content area. So first of all, let's do a div tag with an ID equal to ninjas. And then within this div, I want to do a ul tag, and then in this ul tag is where we're going to output all of these different ninjas. So each ninja is going to have an li tag, right? And how do we do this? We can use v-for. We've learned that in the previous tutorial. We can use v-for to cycle through all of these and output each one.
So let's create an li tag and then we'll say v-for to cycle through these. And we're going to say ninja in ninjas, which is this property right here, remember. And then we're going to also attach a click event to this. So v-on, and then it's going to be a click. And then that's going to be set equal to ninja.show = !ninja.show. And I'm going to explain this in a second. So basically what we're doing is for each ninja, we're outputting this li tag, right? And we're attaching a click event to each li tag that we output. And what we're saying is when we click this particular li tag, which corresponds to a particular ninja, then I want you to get the show property of that, which is this thing, and I want you to negate it. I want you to turn it around. So if it's currently false, turn it to true. If it's currently true, turn it to false. That's what this thing here does right there. Okay, so that's going to toggle this show property right here between true and false.
So within this li tag now, what we want is a h2 and this is going to be the ninja name. So we can just output that as normal, so ninja.name like so. And then we also want a h3 and this is going to be this thing right here, the specialty. Okay, so first of all, let's output that. We'll say ninja.speciality. Okay. Now, I only want this to show, remember, when show is true. So we can use v-show to do that. We learned this in a previous tutorial. So v-show, we set that equal to a boolean, right? And if this boolean is true, then this thing will show. If it's false, then this thing will not show. So all we're going to do is set it equal to this property right here, so it can detect whether it's false or true. So we'll set it equal to ninja.show. So when we're clicking on this li tag now, this property right here is toggling between true or false. Therefore, this will either show or hide depending on whether this is true or false. Okay, so there we go.
That is the kind of template we need. I just want to add a little bit of styling as well. Now we've got scoped already attached there and in fact, what I'm going to do is just copy and paste this from my repo. You can get it all from that same repo. So all I'm doing is giving this ninjas ID right here a width of 100%, a max width of 1,200 pixels, a margin, some padding, and we're saying box-sizing: border-box, so this whole width is taken into account the padding right there and the border if there is one. We're also displaying this ul as a flex and we're saying flex-wrap: wrap, so that the li items or the list items within it are going to wrap. We're giving a list-style-type of none and no padding. We're saying with the li a flex-grow of 1 so they're all going to grow equally. The flex-basis is 300 pixels, so when they reach 300 pixels, they're going to wrap because they can't go any smaller than this flex-basis. Text align to the center, padding 30 pixels, we've got a border and a margin.
Integrating the Ninjas Component & Final Demo
Okay, so let's save this now and we want to import this dude into the root component. So let's go back here and we want to import it right there. But first of all, remember, we have to import it down here. So let's copy that dude, paste it down below. This time we want to import Ninjas from './components/ninjas.vue'. Okay. And we want to add it to this components property right here. So we'll call this app-ninjas.
Now, we could just call this ninjas without the app- but I want to keep things consistent, so we'll call it app-ninjas and this is going to be the Ninjas component thing we just imported right here. So now we can add it here in the middle, app-ninjas. Save that and let's check this out in a browser. And now you can see all of these panels right here. These are all the ninjas being output. When we click one, it shows the specialty of that ninja, right? And when we click one again, it takes away the specialty of that ninja, it toggles it. Pretty cool, right?
Final Thoughts
So that is a basic little project we can create very quickly with Vue.js using nested components. And look, I know the style of this website or web page is pretty crappy, but guys, that is not the point of this tutorial. I just want to show you how we can nest components. The styling is all up to you.