Livewire component that updates the cart counter

Nav • May 30, 2020

laravel livewire
Our task

Let's say we have a button that adds a product to the cart dynamically. Maybe it does this through VueJS component, Javascript, or in our case a Livewire component. We want to update the counter every time the user adds an item in the cart. We'll use Livewire to do this. Quick sample below..

Livewire add to cart counter button

Here's a link in case you need to install and configure Livewire in your Laravel app.

Start by creating a Livewire component:

php artisan make:livewire CartCounter

This will create a boilerplate class app/Http/Livewire/CartCounter.php and a view resources/views/livewire/cart-counter.blade.php.

Let's start with the easiest part, updating the view.

// cart-counter.blade.php.
<span>
    @if($show)
        <span class="badge badge-danger">
            {{ $count }}
        </span>
    @endif
</span>

Here we show the span if $show variable is true. The $count variable will hold the number of items in the cart. We'll place this view in a blade navigation partial.

// navigation.blade.php
 <li>
    <a  href="/cart" class="menu-link">
        <span class="menu-link-text">
            Cart
            <livewire:cart-count>
        </span>
    </a>
</li>

<livewire:cart-count> will render a badge beside the Cart link, containing a counter.

The CartCounter.php class contains all the logic. Below is the component class.

// CartCounter.php
<?php

namespace App\Http\Livewire;

use Livewire\Component;
use App\Item;
use Auth;

class CartCount extends Component
{
    public $show = false;

    public $count = 0;

    protected $listeners = ['updateCartCount' => 'updateCount'];

    public function mount()
    {
        $this->updateCount();
    }

    public function updateCount()
    {
        $this->count = $this->getCount();

        if ($this->count > 0) {
            $this->show = true;
        } else {
            $this->show = false;
        }
    }

    public function getCount()
    {
        $user = Auth::user();
        $cartCount = Item::where('user_id', $user->id)->whereNull('order_id')->get()->count();
        return $cartCount;
    }


    public function render()
    {
        return view('livewire.cart-count');
    }
}

Okay, so $show variable shows and hides the badge, and the $count is the number of items in the cart, those two are pretty straightforward. protected $listeners will trigger an count update, this requires a deeper explanation. We'll cycle back to this shortly.

When the component gets mounted, updateCount is executed. This method checks the current count by executing the getCount method. It updates the count variable, and decides if the badge should be rendered or not. If the count is greater then 0, it shows the badge, otherwise it hides it. The getCount method checks the database for a number of items in the user's cart.

The missing part of the puzzle is the Add to Cart button. We will trigger all this reactivity through firing an event in the add to cart component. Which in this case happens to be a Livewire component. So from within that component, we can fire an event to update the count.

$this->emit('updateCartCount');

Then, with protected $listeners = ['updateCartCount' => 'updateCount']; in the CartCounter.php we can catch that event. This event can be fired from a view, CartCounter class, or Javascript if you wanted to. Check out the Livewire docs for a bit more info.