Skip to main content

Black Friday 2025! Only until December 1st: coupon FRIDAY25 for 40% off Yearly/Lifetime membership!

Read more here
Premium Members Only
Join to unlock this tutorial and all of our courses.
Tutorial Premium Tutorial

Livewire Sidebar Filters for E-Shop Products: Step-by-Step

May 02, 2023
10 min read

Have you ever needed a checkbox-based filter for a list, like in e-shop sidebars? In this tutorial, we will use Livewire to build this step-by-step and update the products list without page refresh.

filtered products

Notice: the link to the repository will be at the end of the tutorial.

We will use Livewire features like Events and Lifecycle Hooks to achieve the end result.

So let's dive in!


Laravel Project Preparation

For this demo, we'll use our own Laravel Breeze Pages Skeleton which will give us a Breeze-like layout but with a public page for the products list.

As you saw in the screenshot above, we will filter by three criteria:

  • Price (within the Product itself)
  • Category (a belongsTo relationship)
  • Manufacturer (a belongsTo relationship)

So first, we need Models and Migrations for all of them.

php artisan make:model Category -m
php artisan make:model Manufacturer -m
php artisan make:model Product -m

database/migrations/xxxx_create_categories_table.php:

public function up(): void
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}

app/Models/Category.php:

class Category extends Model
{
protected $fillable = [
'name',
];
 
public function products(): HasMany
{
return $this->hasMany(Product::class);
}
}

database/migrations/xxxx_create_manufacturers_table.php:

public function up(): void
{
Schema::create('manufacturers', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}

app/Models/Manufacturer.php:

class Manufacturer extends Model
{
protected $fillable = [
'name',
];
 
public function products(): HasMany
{
return $this->hasMany(Product::class);
}
}

database/migrations/xxxx_create_products_table.php:

public function up(): void
{
Schema::create('products', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->text('description');
$table->decimal('price');
$table->foreignId('category_id')->constrained();
$table->foreignId('manufacturer_id')->constrained();
$table->timestamps();
});
}

app/Models/Manufacturer.php:

class Product extends Model
{
protected $fillable = [
'name',
'description',
'price',
'category_id',
'manufacturer_id',
];
 
public function category(): BelongsTo
{
return $this->belongsTo(Category::class);
}
}

Livewire Components

Next, after the installation of Livewire itself, we will need two Livewire components:

  • One to show the products
  • And another one for a sidebar with filters

When we click on any filter in the sidebar, the event will be sent to the Products component.

php artisan make:livewire Products
php artisan make:livewire Sidebar

First, let's just show filters and products, and later we will actually make filters work.

Here's how to add Livewire components in the Blade...

Premium Members Only

This advanced tutorial is available exclusively to Laravel Daily Premium members.

Premium membership includes:

Access to all premium tutorials
Video and Text Courses
Private Discord Channel

Comments & Discussion

V
Velkacem ✓ Link copied!

Thank you for this tutorial, i have onequestion please, How to add pagination for this Filter?

PK
Povilas Korop ✓ Link copied!

Well, it's not easy to answer in a comment. But basically, you just change Product::withFilters(...)->get() to Product::withFilters(...)->paginate() and add the pagination links.

You may also use Livewire pagination: https://laravel-livewire.com/docs/2.x/pagination

V
Velkacem ✓ Link copied!

I have a problem when I change pages with pagination, the filter no longer works, the display returns to the start

GK
Geovane Kruger ✓ Link copied!

You add use WithPagination; on the component Livewire?

V
Velkacem ✓ Link copied!

I added it but still the same problem

LA
Luis Antonio Parrado ✓ Link copied!

In the Livewire component app/Http/Livewire/Products.php change

protected $selected = [ 
        'prices'        => [],
        'categories'    => [],
        'manufacturers' => []
    ];

to

public array $selected = [
        'prices' => [],
        'categories' => [],
        'manufacturers' => [],
    ];

and add $this->resetPage(); to method setSelected

GK
Geovane Kruger ✓ Link copied!

I personally prefer to use $this->emitTo(Products::class, 'updatedSidebar', $this->selected); It makes the code easier to read.

V
Velkacem ✓ Link copied!

please can you provide me the complete code on github?

BM
Bradley Miller ✓ Link copied!

app/Models/Manufacturer.php:

class Product extends Model { protected $fillable = [ 'name',

I think that should be

app/Models/Product.php:

PK
Povilas Korop ✓ Link copied!

Of course! Nice catch, fixed.

JN
Jeff Norris ✓ Link copied!

Very good, BUT for this (& similar) use case one should probably consider investing the time in Scout (using Algolia or Meilisearch) and InstantSearch.js for scalable UI/UX.

See for example InstantSearch.js widget showcase which is this exact example.

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.