N. Arifin
N. Arifin

Reputation: 25

How to Filter Data By Checkbox Using Livewire Laravel

I want to make a filter by checking, in this case, I have one Course table and in this table I include Level Field, where the customer can filter the course by level, for example I have levels like Beginner, Intermediate, and soon. So, my problem is I want to display Level start form ALL, BEGINNER, INTERMEDIATE and soon, so how I can make when they click ALL then all data display than when they checked Beginner and Intermediate then the data where has Beginner and Intermediate value display all not one of them. anyone, please help me, I don't have any idea about this. so far this my code come from Livewire/SearchCourse:

public $all,$beginner,$intermediate;

public function render()
{
    return view('livewire.search-course', [
        'courses' => Course::when($this->beginner, function ($query, $term){
            return $query->where('level', 'LIKE', "%$term%");
        })
            ->paginate(10)
    ]);
}

And this is my code on blade for checkbox:

<div class="card-body border-top">
    <span class="dropdown-header px-0 mb-2">{{ __('Skill Level') }}</span>
    <!-- Checkbox -->
    <div class="form-check mb-1">
        <input type="checkbox" class="form-check-input level-checked" wire:model="all"
               id="level" name="level" value="">
        <label class="form-check-label" for="all">All</label>
    </div>
    <div class="form-check mb-1">
        <input type="checkbox" class="form-check-input level-checked" wire:model="beginner"
               id="level" name="level" value="beginner">
        <label class="form-check-label" for="beginner">Beginner</label>
    </div>
    <div class="form-check mb-1">
        <input type="checkbox" class="form-check-input level-checked" wire:model="intermediate"
               id="level" name="level" value="intermediate">
        <label class="form-check-label" for="intermediate">Intemediate</label>
    </div>
</div>

Thank u so much for any help.

Upvotes: 1

Views: 2850

Answers (3)

Qirel
Qirel

Reputation: 26460

I would rather suggest that you push all the checkboxes into an array, this will make filtering much more simple.

public $courseLevels = [""]; // Default is empty, so "All" is checked

public function render()
{
    return view('livewire.search-course', [
        'courses' => Course::when(count(array_filter($this->courseLevels)), function ($query) {
            return $query->whereIn('level', $this->courseLevels);
        })
        ->paginate(10)
    ]);
}

Then set the wire:model of all your checkboxes to wire:model="courseLevels",

<div class="card-body border-top">
    <span class="dropdown-header px-0 mb-2">{{ __('Skill Level') }}</span>
    <!-- Checkbox -->
    <div class="form-check mb-1">
        <input type="checkbox" class="form-check-input level-checked" wire:model="courseLevels" value="" id="all">
        <label class="form-check-label" for="all">All</label>
    </div>
    <div class="form-check mb-1">
        <input type="checkbox" class="form-check-input level-checked" wire:model="courseLevels" value="beginner" id="beginner">
        <label class="form-check-label" for="beginner">Beginner</label>
    </div>
    <div class="form-check mb-1">
        <input type="checkbox" class="form-check-input level-checked" wire:model="courseLevels" value="intermediate" id="intermediate">
        <label class="form-check-label" for="intermediate">Intemediate</label>
    </div>
</div>

This will mean that if you have no checked checkboxes at all, or if the only value is empty (your "All" value), then the first argument to when() is false, because count(array_filter($this->courseLevels)) will only count values that are non-empty - and everything will be returned. When there are values, the first argument to when() is true, and you will add the filter to limit the course-levels. I'm assuming that the levels are actually intermediate and beginner, so that we don't need the LIKE operator, and can use whereIn() instead.

Upvotes: 1

Prospero
Prospero

Reputation: 2352

If at least you handle some function to uncheck previous filter selected, I suggest change it to use radio-buttons or select element. In my example, you can do it using a select element to filter the table

use WithPagination;

public $filter = "";

public function render()
{
   return view('courses-component', 'courses' => $this->getData());
}

public function getData()
{
   return Course::where('level', 'LIKE', "%" . $this->filter . "%")->paginate(5);
}

and in view

<div class="card-body border-top">
   <select class="form-control" wire:model="filter">
     <option value="">All</option>
     <option value="beginner">Beginner</option>
     <option value="intermediate">Intermediate</option>
   </select>
</div>

Upvotes: 0

kenean50
kenean50

Reputation: 588

You can do something similar to the following with Lifecycle Hooks

public $courses = [];

public $filters = [
    'all' => false,
    'beginner' => false,
    'intermediate' => false,
];

public function updatedFilters()
{

    $result = new Collection();

    if ($this->filters['all']) {

        $result = $result->merge(Course::where('level', 'LIKE', "%all%"));

    } elseif($this->filters['beginner']) {

        $result = $result->merge(Course::where('level', 'LIKE', "%beginner%"));

    } elseif($this->filters['intermediate']) {

        $result = $result->merge(Course::where('level', 'LIKE', "%intermediate%"));
    }

    $this->course = $result->paginate(10);
}

And these on your view

<div class="card-body border-top">
    <span class="dropdown-header px-0 mb-2">{{ __('Skill Level') }}</span>
    <!-- Checkbox -->
    <div class="form-check mb-1">
        <input
            type="checkbox"
            class="form-check-input level-checked"
            wire:model="filters.all"
            id="level"
            name="level"
        >
        <label class="form-check-label" for="all">All</label>
    </div>
    <div class="form-check mb-1">
        <input
            type="checkbox"
            class="form-check-input level-checked"
            wire:model="filters.beginner"
            id="level"
            name="level"
        >
        <label class="form-check-label" for="beginner">Beginner</label>
    </div>
    <div class="form-check mb-1">
        <input
            type="checkbox"
            class="form-check-input level-checked"
            wire:model="filters.intermediate"
            id="level"
            name="level"
        >
        <label class="form-check-label" for="intermediate">Intermediate</label>
    </div>
</div>

Upvotes: 0

Related Questions