Skip to main content
Premium Members Only
Join to unlock this tutorial and all of our courses.
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
Velkacem avatar

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

Povilas Korop avatar

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

Velkacem avatar

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

Geovane Kruger avatar

You add use WithPagination; on the component Livewire?

Velkacem avatar

I added it but still the same problem

Luis Antonio Parrado avatar
Luis Antonio Parrado

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

👍 1
Geovane Kruger avatar

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

👍 1
👀 1
Velkacem avatar

please can you provide me the complete code on github?

Bradley Miller avatar

app/Models/Manufacturer.php:

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

I think that should be

app/Models/Product.php:

Povilas Korop avatar

Of course! Nice catch, fixed.

Jeff Norris avatar

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.