Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

mallaury's avatar

Livewire - Multiple checkboxes (all checked when only one value is...)

Hello,

I am using Livewire 2.3 I would like to filter products with checkboxes (categories and subcategories). But, when I go to this page : /shop?categories=clothes All checkboxes are visually checked (according to the debugbar there is only "clothes" in the variable).

Here is my blade :

<div class="d-flex align-items-center">
  <input type="checkbox" wire:model="categories" value="clothes" id="clothes">
  <label for="clothes">clothes</label>
</div>
<div class="d-flex align-items-center">
  <input type="checkbox" wire:model="categories" value="shoes" id="shoes">
  <label for="shoes">shoes</label>
</div>

Here is my component :

class Collection extends Component
{
    public $current_categories;
    public $current_subcategories;

    public $search_result;

    // Get filtered categories
    public $db_categories = [];
    public $db_subcategories = [];
    
    protected $queryString = [
        'current_categories' => ['except' => '', 'as' => 'categories'],
        'current_subcategories' => ['except' => '', 'as' => 'subcategories'],
    ];

public function mount()
    {
        $this->categories = Category::whereNull('parent_category_id')->with(['subcategories'])->get();

        $this->updatedCurrentCategories($this->current_categories);
        $this->updatedCurrentSubcategories($this->current_subcategories);
    }

public function updatedCurrentCategories($values)
    {
        $array_current_categories = $values ? explode(',', $values) : [];
        if ($array_current_categories) {
            $this->db_categories = Category::whereIn('slug', $array_current_categories)->get();
        }
    }

public function filter()
    {
        // Query to fetch products according to the $db_categories (filters)
    }

public function render()
    {
        $this->search_result = [];
        $this->filter();
        return view('livewire.shop');
    }

I tried to split the model this way: wire:model="categories.clothes". It works, but I do not want to do it this way. Because I want to keep a clean URL.

Thanks for your help!

0 likes
9 replies
tykus's avatar

What instance property is receiving the categories from the form; you have a $categories property that is your Collection of Category instances? Sort out your class properties!

mallaury's avatar

@tykus $current_categories : will store a list of slug (the checked slugs wired with the form) $db_categories : is the collection of categories checked (fetched from the lit of slugs that is used to filter products) $categories : is the list of categories (displayed in a foreach)

Snapey's avatar

@mallaury your checkboxes use wire:model="categories"

You have no such attribute in your Livewire component

mallaury's avatar

@Snapey You are right. I wrote the alias. But it does not work anyway. I think I must split the property this way : wire:model="current_categories.1" because livewire can not store differents values for the same property in URL.

// I wanted to do this way
wire:model="current_categories"
/shop?categories=clothes,shoes

// But I think I must do this way
wire:model="current_categories.1"
/shop?categories[0]=clothes&categories[1]=shoes

Am I wrong?

Snapey's avatar

@mallaury do you have a public array of current_categories in your livewire component?

mallaury's avatar

@Snapey My blade :

@foreach($categories as $category)
    <input type="checkbox" wire:model="current_categories">
@endforeach

My component :

class Collection extends Component
{
    public $current_categories = [];
    public $search_result;

    // Get from DB (once)
    public $categories = [];

    // Fetched from database
    public $db_current_categories = [];
    
    protected $queryString = [
        'current_categories' => ['except' => [], 'as' => 'categories']
    ];

    public function mount()
    {
        $this->categories = Category::whereNull('parent_category_id')->get();

        $this->updatedCurrentCategories();
    }

    public function updatedCurrentCategories()
    {
        $array_current_categories = $this->current_categories ? explode(',', $this->current_categories) : [];
        if ($array_current_categories ) {
            $this->db_current_categories = $this->categories->whereIn('slug', $array_current_categories);
            $this->current_categories = array_filter($array_current_categories );
        }
    }
    
    public function filter()
    {
        // Sql query
    }

    public function render()
    {
        $this->search_result = [];
        $this->filter();
        return view('livewire.collection');
    }
}

To summarise, this is a page that filters products. The filters selected must appear in the URL. If I access this page via this url :

/shop?categories=clothes,shoes

I want the clothes and shoes categories to be checked.

Thanks for your help!

Snapey's avatar

forget querystring for the moment, and comment out anything in your component that might try to affect current_categories

Then set a value on each checkbox

finally place somewhere in the view something that shows the $current_categories

Please or to participate in this conversation.