Introduction to Auto-Importing Components
Alright then, so you've probably already noticed this, but when we use components like the Nuxt link component that's built into Nuxt, we don't have to manually import those components into the file. Next auto-imports them where we use them. And the same is true for any components that we're going to make ourselves in the future. But what we do have to do is we have to put all of those custom components in a folder in the root of the application called components.
So make that folder first of all, and then any components that you make in this folder can be used in other components or pages without needing to manually import them. Nuxt is going to do that automatically for us. So in this lesson, I'm going to make a couple of custom components: a card component for each of the products on the product listing page, and also a product details component which can be then added to the product details page. So let's start by adding a component which is going to be a product card, and that product card is going to be output in the product index component right here instead of just a link. So let's create inside the components folder a new file and call it ProductCard.vue.
Creating and Nesting the ProductCard Component
like so. And then inside here, I'm going to say vbase- and then it's this one right here. And now what I want to do is nest this component inside the index page right here, inside the products folder. So instead of just outputting the link, I'm going to cut that and I'm going to output the ProductCard, like so.
Now, I've not needed to import this anywhere. Nuxt automatically does that for us because it looks inside this components folder for the ProductCard component. What I do want to do is pass in a product prop and that's going to be equal to 'p'. This is dynamic, so I need to do a colon right here, otherwise it would just pass in the string value of P. So we're passing in that prop and we need to accept it over inside this component now.
Accepting Props with defineProps
So, the way we do that inside the script tag is by saying const and then destructuring a prop which is called product—that's what we called it right here, product—and then we set that equal to defineProps, which is a function we get with Nuxt. And then that function takes an argument. It's going to be an array of different props we want to accept. We're going to use string values for the props, so we want to accept the product prop. So we grab that now and now we can use it in the template.
Building the ProductCard Template
So what do we want to do in this template? Well, first of all, I want to apply some classes to this div and the first class is a class of card. Now, that's going to be a custom class that I create shortly. For now, I also want to add some Tailwind classes, so text-center. And then inside the div we want to output the different things.
Now, the first thing I want to do is output an image tag for the product. Now when we get a response for a single product from the API, we also get an image property on the product. And that image property is the source of that image. So we can just output it here. So, this we can data bind to, and inside I'm going to... in fact, we don't need to do that, we can just say product.image, like so. And that's going to output the source of the product. For alt, we'll just say, I don't know, "product thumb". And then also I'll give this a class as well, equal to thumb, just in case we want to style that.
All right. So down here, I'm going to do a paragraph tag and this is going to be for the product title. So product.title in curly braces. We're also going to give this some classes, so class is equal to font-bold. These are just Tailwind classes. text-gray-500, m-4 so it's got some margin all the way around, and also truncate as well. So what that truncate class does is basically add those three little dots at the end of the title if it goes over one line.
Adding the Link and Custom Styles
Okay, so after the title, we also want to output the link to the product details page. Now, do I still have that? Yes, I do. Okay. So, a Nuxt link. This is where we want to go to using the product ID. We need to change that to product this time. And then instead of outputting the title, I'm just going to say "View Details" or something like that. But it's going to be a button.
So let's do inside here a p with a class of button... oops, that's not worked. Okay, let's do this manually. class is equal to btn. Remember that was that custom component class we created, and then also give it some margin in the y direction and that's going to be my-4, and we'll say "View Details", like so. Okay.
So dead simple. I also want to add some styles for the thumb. So let me do that down here like so. And also we have this class of card as well. So I'm going to create some styles inside the tailwind.css file for that. Now what I'm going to do is just grab these from my repo because I can't remember how to style it, so I'm just copying and pasting and we're going to place it here as a component. .card and we apply these classes: p-3, rounded-lg, bg-white, shadow-md, and h-full. So let me save that now.
Reviewing the Product List Page
and now I think that's pretty much it. So now for each product inside this index page over here, we output this product card and pass through the product as a prop and we use that to output the details for that product, including an image, the title, and also this thing right here where it says view details. Okay, so hopefully now, I think that's pretty much all we need to do. We could output the price as well, but I think we'll output the price on the product details page. Let's view this now in a browser. Alright, so now on the products page, that's looking a lot better. Now we have this card component for each individual product. So these buttons are a bit wide, we'll sort that in a second, but also when we go to View Details, this page still looks stripped. So now what I'd like to do is make a component for outputting the product details as well and then nest that on the product details page.
Creating the ProductDetails Component
All right then, so now I'm going to create that next component. So let's create a new file and this is going to be called ProductDetails.vue. And then inside here let's just flesh this out, vbase-3, and then we can go ahead and nest this inside the details page right here. So instead of outputting all this over here, what we're going to do is just output the ProductDetails component, like so.
Now, we need to pass in as a prop the product so that we can use that inside the product details component. So let's do that. Call that prop product and we set it equal to product. All right. So now inside the Product Details component, we can accept that prop. And remember the way we do that is by saying const and then destructuring whatever prop we want, so product in our case. And then we... oops, don't put this in style, inside the uh, the style tag, that's for sure... but inside the script. And then we set that equal to defineProps and then an array and then product. All right, so we have now the product in this template, and we can output the details.
Building the ProductDetails Layout
So what I'm going to do is first of all give this a class equal to card. Now we have card over here as well and they were small little cards in a grid, but when we use it on this page, it's not in a grid and it's going to be full width. It's just to give it that kind of extra bit of styling, so it stands out on the page a little bit. So inside that div, I want to then split the product details page into two sections: one on the left for the image and then one on the right for all the details. So let's do another div right here and then give this a class of grid so we can split this up into two columns. So we'll say grid-cols-2 and then gap-10 to give it a massive gap.
Alright, so inside there we want two things. On the left we want the image. So let's do a div for that. In fact, I'm going to give this a class of p-7 to give you some padding all the way around. So inside this div we'll do an image tag now. And remember we have access to the product as a prop, so I'm going to data bind to this and say product.image to get us the source of that image. And then as an alt, I'll just say "product image". And then also we need to apply some classes to this so we'll say class is equal to mx-auto to give it auto margin left and right and then my-7. Alright so that's all we need on the left.
Adding Product Information and Text Styling
On the right hand side, on the right column, we need another div for all of the product details. So let's do that. And also let's give this some padding as well so class is equal to p-7. Alright, so inside here we want to output the product title, the price and maybe the product description. So let's do an H2 for the title first of all, and apply some classes to this. So I'm going to apply text-4xl and then my-7 to give it some margin in the y-direction.
Now, if you're just joining on this lecture, by the way, on this lesson, you might be thinking, where are these classes coming from? Well, before we installed Tailwind, so these are all Tailwind classes. So let's output the product.title right here. And then below the h2, I'm going to do a paragraph tag for the price. So I'm going to give these a few classes right here. So the first one is going to be text-xl and then my-7 again. So inside this paragraph tag, we'll say "Price - " and then we'll do it in dollar signs. And then to output a variable, double curly braces, and it's product.price. So it's going to be the price, which isn't prefixed with any kind of currency sign, so that's why we're adding the dollar sign right here.
Okay, so an H3 and then we need to apply classes to this. So the class is equal to font-bold, border-b-2, and then mb-4 and then pb-2. And then we'll say right here "Product Description:". And then below that, we'll do a paragraph tag for the description. So we'll output that right here. So product.description. These are all properties on the data we get back. I'm not just making them up, they come from the API. And we also give this a class of mb-7 to give it some margin bottom.
Finalizing and Reviewing the Details Page
And I think that's pretty much it. I am going to add one more class to the image or rather we'll just style it down here. We'll say image and then these styles are scoped to this component so it's only going to apply to this image. And for this image, we'll say the max-width is going to be 400 pixels, just so it's not huge on the page. All right.
So we've created this product details component, we've nested it inside this component right here, this ID page, the product details page. So hopefully now when we go to each product details page, we're going to see all of the product details for that product. All right and so let's click on one of these. And yeah, that's looking good. Image on the left, the details on the right in this giant card component as well. And then if we go over here, you can see a different one. Yep, this is all working. Awesome. Cool. So, next lesson, what we're going to do is talk about error pages.