Applying Filter using BelongsToMany Relationship in Livewire

100r0bh

Saurabh Mahajan

Posted on October 6, 2021

Applying Filter using BelongsToMany Relationship in Livewire

In this Tutorial, we will see how to Filter Records using a BelongsToMany Relationship in Livewire. This is the part 6 of the Series related to adding New Functionality to a Table using Livewire. In Last Part of the Series we implemented Filter on the BelongsTo column of the Product Model using Livewire.

Lets say our Product Model has belongsToMany Relationship with Category as follows

    public function categories()
    {
        return $this->belongsToMany(Category::class);
    }
Enter fullscreen mode Exit fullscreen mode

That means there is a Category Table which holds all the Categories. And then there is a Pivot Table which links Products and Categories. And we want to Filter using Category, so when the User selects a Category we will display only those Products which are related to that Category.

First of all we will fetch all the Categories. We would create a categories property and populate it in the mount method.

$this->categories = Category::pluck('name', 'id')->toArray();
Enter fullscreen mode Exit fullscreen mode

And in the View, we would create the dropdown by looping through these categories.

<div>
    <label>
        Categories
    </label>
    <select>
        <option value="">Any</option>
        @foreach($categories as $category_id => $category_name)
        <option value="{{$category_id}}">{{$category_name}}</option>
        @endforeach
    </select>
</div>
Enter fullscreen mode Exit fullscreen mode

The Dropdown will have all the Categories that User can select from. As usual we also have an Any option so as to display all the Products.

Next we will create a property called $selectedCategory and link it with above dropdown using wire:model.

<select wire:model="selectedCategory">
    ....
    ....
</select>
Enter fullscreen mode Exit fullscreen mode

This way whenever User changes the above Dropdown, the property $selectedCategory would be updated in the Component and Livewire will re-render the component. Now all we need to do is to change the Query to reflect the value of Selected Category.

Below is the current Query that we have.

public function query()
{
    return Product::query()
        ->when($this->selectedStatus, function($query) {
            return $query->where('status', $this->selectedStatus);
        })
        ->when($this->selectedBrand, function($query) {
            return $query->where('brand_id', $this->selectedBrand);
        });
}
Enter fullscreen mode Exit fullscreen mode

We will include another when Condition and we would filter the records using whereHas Clause like below:

->when($this->selectedCategory, function($query) {
    return $query->whereHas('categories', function($query) {
        return $query->where('categories.id', $this->selectedCategory);
    });
});
Enter fullscreen mode Exit fullscreen mode

Go ahead and test it, our Filter should be working now. So unlike the previous Filters where we were able to apply the Query directly on the Product Model, here we had to pass a Closure to whereHas in order to Filter using BelongsToMany Relation.

If you have liked this Tutorial, please checkout the Livewire Package tall-crud-generator which automatically generates all the Code related to applying Filter on a BelongsToMany Relation.

💖 💪 🙅 🚩
100r0bh
Saurabh Mahajan

Posted on October 6, 2021

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related