Applying Filter using BelongsToMany Relationship in Livewire
Tags: laravel, livewire
Published: 2021-10-06 08:50:22

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](https://dev.to/100r0bh/applying-belongsto-filter-to-table-using-livewire-1elp) 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);
    }
```

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();
```

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>
```

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>
```

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);
        });
}
```

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);
    });
});
```

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](https://github.com/ascsoftw/tall-crud-generator) which automatically generates all the Code related to applying Filter on a BelongsToMany Relation.