Overview of Props0:05
One of the simplest methods for managing state in view is through the use of props. Let's explore our example. We have a small web shop with a few products being displayed, and in the header we have a card icon that opens a card overlay. If you open up app view, we'll see a few components. We have a net bar component, we have our card overlay component,
We have a net bar component, we have our card overlay component, and down here we loop over all products and render a ProductCard for it. Our products are defined below and consist of an id, a title, a description, and a price. If you dive into the ProductCard component, we'll see we define a prop product that's required of type object, and in the template we'll see we render a title,
Wiring Stepper Events0:43
of type object, and in the template we'll see we render a title, a description, and a nicely formatted price based on this product. Now this web shop feels a bit static, so let's add our card functionality. We'll start by adding our stepper component to the product card. Let's import it and if we dive into the stepper component, we'll see it emits a decrement event.
Let's import it and if we dive into the Stepper component, we'll see it emits a decrement event. When we press the minus icon and an increment event when we press the plus icon, let's listen to these events in our ProductCard component and let's emit it up to the parent and let's pass our product with it. And let's do the same for decrement back in our App view. We'll want to respond to these events and do our state mutations.
We'll want to respond to these events and do our state mutations. So let's add or increment listener and create our handler. Let's create our handler cons. IncrementProduct equals a function that accepts a product. And let's log something to the console. Now when we press the plus button, we'll see we get our log as expected. Let's do the same for decrement. Let's create our handler.
Building Reactive Cart State1:50
Let's do the same for decrement. Let's create our handler. And now when we press decrement, we'll get our log as expected. Alright, now that we can respond to increment and decrement events, we need a way to keep track of our cart. The first thing we'll do is declare a reactive state using ref, let's call it cart, and let's initialize it
ref, let's call it cart, and let's initialize it to an empty array in our incrementHandler. We can now add the selected product to the cart and we can do that as follows. cart, doValue, doPush. I will add the product with a quantity of one. Let's log our cart every time we increment the product. And now every time we press the plus button, we'll see our cart getting filled up.
And now every time we press the plus button, we'll see our cart getting filled up to improve upon this behavior. Let's check if the product already exists in the cart and if it does, we'll just increment the quantity. Let's first search for the value. We can say cart.value.find, and let's check if the productId matches the value.id. If we have a found value, we'll simply increment the quantity and
Displaying Amount in Cards3:04
If we have a found value, we'll simply increment the quantity and otherwise we'll add the product to the card with a quantity of one as follows. And now every time we press the plus icon, we'll see that the quantity increases. Now instead of logging our cart into the console, let's add an amount indication to the product card. To achieve this, let's define a prop on the product card called cart, heads of type array.
To achieve this, let's define a prop on the ProductCard called cart, heads of type array. And let's make it required. Next up, let's pass our card to the ProductCard and we can do that as follows. Finally, backend ProductCard. Let's create a computer prop called Amount, and the first thing we'll do is look into the card to see if we can find a product that matches the prop that we got.
to see if we can find a product that matches the prop that we got. And if we do, we'll return the quantity and if we don't, we return zero. We'll pass the amount into the stepper as follows. And now every time we press the plus icon, we'll see that the amount increases. Let's also change the background color of our product card based on whether or not there's a product in the card.
of our product card based on whether or not there's a product in the card. If we go to the template, we can remove the bg-white class instead. Let's say class equals an array and if the amount is greater than zero, we'll add bg-amber-100 and otherwise we'll say bg-white. And now the background of the cart changes when the amount is greater than zero. All right, so now we can increment a product,
amount is greater than zero. All right, so now we can increment a product, but let's also make sure we can decrement a product back in app view. We'll complete the decrementProduct function like above. First, we'll need to look into the cart and see if we find a matching product as follows. And if we do, we decrement the quantity by one. And if the quantity is lesser than or equal to zero, we'll remove the product from the cart.
And if the quantity is lesser than or equal to zero, we'll remove the product from the cart entirely and we can do that by simply filtering out the product and assigning that new value to our cart. Now we can both increment and decrement our product. Let's take a quick moment to reflect on what we achieved. We added our stepper component and we listen to both the increment and the decrement event. We update, or I should say we mutate our card state.
Connecting Cart Overlay5:13
and we listen to both the increment and the decrement event. We update, or I should say we mutate our card state. We then communicate it back to the ProductCard component, and there we derive a computed property called amount, which we then pass down to the Stepper component and we update the background color based on that amount, all in a reactive manner. Next up, let's make sure our card state is communicated to the CartOverlay so we can display it properly. To do this, we'll jump into cart-overlay.vue.
to the cart-overlay so we can display it properly. To do this, we'll jump into cart-overlay.blade.php and we'll define a prop called cart, which is required end of type array. To display the actual card, I created a card component called Cart, which we can add here. Let's not forget to import it. And let's pass our cart property. Finally, let's go back to app.blade.php.
And let's pass our card property. Finally, let's go back to app view and pass our card property down to the cart overlay where we add a few products to the cart, open the cart overlay. We'll see that our card component is able to render the rows beautifully. We still need to calculate the subtotal in the cart overlay, so let's do that. Now, like before, let's create a computed property.
overlay, so let's do that. Now, like before, let's create a computed property cardSubtotal. Let's not forget to import computed. There we go. We can calculate the subtotal by using reduce as follows, we have a total and we have our product and we will increment our total with the price of the product multiplied by its quantity and we'll default back to zero. And finally, we return a nicely formatted string.
and we'll default back to zero. And finally, we return a nicely formatted string. Let's not forget to reference it in our template. And now when we add a few items to the cart, we'll see our subtotal being calculated correctly. Finally, we have three buttons in our CartRow component that emit an increment, a decrement, and a remove event in our Cart component. Let's listen to these three events and emit it up to our parent.
Let's listen to these three events and emit it up to our parent. In our CartOverlay component, we can listen to these events, but because mutating props is considered an anti-pattern, we'll need to emit these events up to the parent component as follows. Finally, in the parent component, we can listen to the increment and the decrement event and we can bind it to the increment.
to the increment and the decrement event and we can bind it to the increment and the decrement product from before. Now, when we add a few products to our cart, we can also modify the quantity from our cart as follows. Finally, we can also listen on the remove event and let's create that event handle. Removing a product is actually very simple. We reassign the cart to a filtered value of the original cart where we just filter out the product
Prop Drilling Drawback7:51
We reassign the cart to a filtered value of the original cart where we just filter out the product to be removed, and now we can open our cart overlay and we can click remove and we can see it gets removed. Pretty neat. And that wraps up our example. The thing you may have noticed in this setup is that we need to pass our cart state down multiple levels of components. Our app view is the owner of the cart state, which needs to be passed down to the cart overlay, which will then be passed down to the cart,
to be passed down to the cart overlay, which will then be passed down to the cart, which is responsible for rendering the rows. This is called prop drilling, and this is a major disadvantage when managing states using props. In the next lesson, we'll take a look at how we can mitigate this. I hope to see you there.
I hope to see you there.
