Create a Data-Driven Child Component in Vue 3

Share this video with your friends

Send Tweet
Published 2 years ago
Updated 2 years ago

Coding all of your logic inline gets messy fast. Components are a great way to encapsulate logic and make your code a lot more readable.

In Vue, you can pass props to child components so data from the parent can drive the child component. In this lesson, the data will be the crafts from our GraphQL query that we made. We'll display the crafts and use properties on each craft to change the styling of their list item.

Kevin Cunningham: [0:00] Rather than add complexity to this line item in this template, I'm going to create a child component that's going to handle this logic with the more complex need that our query demands.

[0:10] I'll create a new component called craft.vue. I'm going to have a script set up, and I want to pass in a craft object. To do that, I used a globally defined defineProps function that exists in Vue. I'm going to pass in the craft, and that's going to be an object, so we've a variable name and its type.

[0:31] Now I'm going to want a template. For my template, I'm going to, for the moment, just copy in this li. The key and the data will be dealt with in the parent, so I'll get rid of that.

[0:45] Let's import our new craft component and swap out our li for our craft. This is going to be a self-closing component because our craft doesn't have any children or any content that we want to render in the middle. Let's check what that looks like on the frontend.

[1:00] Now, at the moment, that's not rendering anything in our frontend and we're getting an error that our component can't read name. That's because we're not yet passing in our craft variable.

[1:10] We want to bind the property craft to the variable craft that we've destructured from this data right here. We refresh and we have what we need to know the logic for our craft is being handled inside of this template.

[1:24] At the moment, that doesn't look particularly interesting or helpful, so let's make it a bit more useful. Select today paragraph tag around our name and then if this craft has an owner.

[1:34] We know that if v-if="craft.owner" exists, then we want to say that this craft is owned by. Then we want to do is craft.owner.firstName and craft.owner.lastName.

[1:52] We've got these crafts are owned by these people and the ones that don't have an owner currently don't have anything. What we want to do is have an else there. We will have another span which will be a v-else. This span is rendered if this bond fields the logic check here.

[2:08] Inside the span, let's say is available to buy and costs dollars craft.price.toLocaleString, so we can add in any e-commerce that might be there. I'm going to use UK, that's where I'm based. That looks cool.

[2:24] Now to add some styling to show the difference between a craft is owned by someone and a craft is for sale.

[2:31] Back in our template we're going to bind the class of our list item based on whether or not the craft.owner exists. Similarly to our v-f down here, we should turn a real operation with say, if you have an owner, let's give it a class of owned. Otherwise, let's give it a class of for-sale.

[2:48] Let's check if that's worked. We'll inspect this element, and we'll see it has a class of owned. Then we will inspect this element, and we'll see it's got a class of for-sale. Cool.

[3:01] Let's add a scoped style and deal with the owned class and the for-sale class. If it's for sale, we're going to give it a font-weight of 800. Then this is for sale, maybe a background color of a knocked-back gray, so 20, 20, 20, .3, something like that.

[3:27] Then, let's do all of our lis. Let's give them a bit more styling. Let's give them a border of 1 pixel, black and solid. Let's give them some border-radius, 4 pixels. Let's give it a padding, maybe 6 pixels, see what that looks like.

[3:43] We're trying to get something that's data driven and is communicating something to our user. We've captured that logic in our craft component that then we're using over here.