Build a Custom Multi-Column Checkbox Dropdown in Filament

Learn how to build a user-friendly multi-column custom checkbox dropdown using Laravel Filament to provide improved and better selection options for your users.

Filament is a powerful admin panel for Laravel, but sometimes your UI needs go beyond its built-in fields. In this tutorial, we’ll walk through how to build a custom checkbox dropdown component in Filament that supports multiple columns and compatible with dark mode.

Goal

We want to display a dropdown that, when opened, shows a list of checkboxes (e.g. for selecting items). The checkboxes should:

  • Be selectable via checkboxes
  • Be arranged in multiple columns
  • Store selections in a Livewire model
  • Work with dark mode

The purpose for this component is, I have a list of more than 100 entries. If I take CheckboxList component, all of these entries take so much space in UI. Similarly, If I add multiselect Select component, It will not show all entries at once and user have to type name to search for entries.

So, dropdown will reduce the space in UI and checkboxes solve searching problem.

Step 1: Create the Custom Field Component

Create the filament custom checkbox dropdown field component file at app/Forms/Components/CheckboxDropdown.php and add the following code.

<?php
namespace App\Forms\Components;

use Filament\Forms\Components\Field;

class CheckboxDropdown extends Field
{
    protected string $view = 'forms.components.checkbox-dropdown';

    protected array $options = [];

    protected int $checkboxColumns = 1;

    public function options(array $options): static
    {
        $this->options = $options;
        return $this;
    }

    public function getOptions(): array
    {
        return $this->evaluate($this->options);
    }

    public function checkboxColumns(int $count): static
    {
        $this->checkboxColumns = $count;
        return $this;
    }

    public function getCheckboxColumns(): int
    {
        return $this->evaluate($this->checkboxColumns);
    }
}

Step 2: Create a blade view file for the component

As mentioned in the component class, create a custom checkbox dropdown component view file at resources/views/forms/components/checkbox-dropdown.blade.php and add the following code.

@php
$options = collect($getOptions())->mapWithKeys(fn ($label, $id) => [(string) $id => $label]);
$jsonOptions = $options->toJson();
$gridCols = match ($getCheckboxColumns()) {
    1 => 'grid-cols-1',
    2 => 'grid-cols-2',
    3 => 'grid-cols-3',
    4 => 'grid-cols-4',
    default => 'grid-cols-1',
};
@endphp

<div
    x-data="{
        open: false,
        toggle() { this.open = !this.open },
        selected: @js($getState() ?? []),
        liveSelected: @entangle($attributes->wire('model')).defer,
        options: {{ $jsonOptions }} || {},
        isSelected(id) {
            return this.selected?.includes(id);
        },
        labelFor(id) {
            if (!this.options || typeof this.options !== 'object') return id;
            return this.options[id] ?? id;
        }
    }"
    class="relative">
    <!-- Trigger Button -->
    <button
        type="button"
        @click="toggle"
        class="w-full border rounded px-3 py-2 text-left bg-white dark:bg-gray-900 border-gray-300 dark:border-gray-700 text-gray-800 dark:text-gray-200 shadow-sm">
        <template x-if="selected?.length">
            <span x-text="selected.map(labelFor).join(', ')"></span>
        </template>
        <template x-if="!selected?.length">
            <span class="text-gray-400 dark:text-gray-500">Select items...</span>
        </template>
    </button>

    <!-- Dropdown Panel -->
    <div
        x-show="open"
        @click.away="open = false"
        x-cloak
        class="absolute z-10 w-full mt-1 rounded border bg-white dark:bg-gray-900 border-gray-300 dark:border-gray-700 shadow max-h-60 overflow-y-auto">
        <ul class="p-2 grid {{ $gridCols }} space-y-1 gap-2">
            <template x-for="(label, id) in options" :key="id">
                <li>
                    <label class="flex gap-2 items-start space-x-2 text-gray-800 dark:text-gray-200">
                        <input
                            type="checkbox"
                            class="fi-checkbox-input rounded border-none bg-white shadow-sm ring-1 transition duration-75 checked:ring-0 focus:ring-2 focus:ring-offset-0 disabled:pointer-events-none disabled:bg-gray-50 disabled:text-gray-50 disabled:checked:bg-gray-400 disabled:checked:text-gray-400 dark:bg-white/5 dark:disabled:bg-transparent dark:disabled:checked:bg-gray-600 text-primary-600 ring-gray-950/10 focus:ring-primary-600 checked:focus:ring-primary-500/50 dark:text-primary-500 dark:ring-white/20 dark:checked:bg-primary-500 dark:focus:ring-primary-500 dark:checked:focus:ring-primary-400/50 dark:disabled:ring-white/10 mt-1"
                            :value="id"
                            :checked="isSelected(id)"
                            @change="
                                if (isSelected(id)) {
                                    selected = selected.filter(i => i !== id)
                                } else {
                                    selected.push(id)
                                }
                                liveSelected = selected;
                            ">
                        <span x-text="label"></span>
                    </label>
                </li>
            </template>
        </ul>
    </div>
</div>

Now this component id ready to use. Currently, it can adopt current filament admin panel theme and you can distribute checkboxes to multiple columns using checkboxColumns option.

Step 3: Usage in Filament Resource

You can use this custom checkbox dropdown component in any resource file as follows:

CheckboxDropdown::make('selected_items')
    ->label('Select Items')
    ->options(Item::pluck('name', 'id')->toArray())
    ->checkboxColumns(3)

Conclusion

With this setup, you can develop a fully reusable, dynamic, and user-friendly multi-column checkbox dropdown — perfect for any Laravel Filament project.

Install the Laravel Filament Panel Builder

Learn to install and set up Laravel Filament, a tool for creating customizable admin panels and CRUD applications. This guide covers requirements, installation steps, and user creation. Follow this concise tutorial to get started with Filament in your Laravel project quickly and efficiently.

Laravel Filament is a powerful tool designed to create Admin panels and manage content in Laravel applications. It provides a highly customizable and developer-friendly interface for creating CRUD applications, dashboards, and various business-related applications. Filament is known for its flexibility and ease of use, allowing developers to scaffold forms, tables and pages quickly without writing a lot of boilerplate code.

This article describes the installation process filament panel over laravel with most of the possible configations and steps.

Requirements

Install and configure the following components, before running any filament command.

  • PHP v8.1+
  • Laravel v10.0+
  • Livewire v3.0+ (Filament composer command will install this package automatically. So, no need to install this package separately.)

Install Laravel Filament Panel

To install the filament panel over laravel, run the following command at the root of the project folder,

composer require filament/filament:"^3.2" -W

This command will install the base package of filament. This will also install livewire package, which is in the requirements.

php artisan filament:install --panels

This command will install the filament panel after some information required to install the panels. It will ask the following questions,

What is the ID?

On the basis of this ID, it will create the panel provide for the filament panel and also register this panel provider.

For Example:
If ID is admin, it will create the panel provide to he following location, app/Providers/Filament/AdminPanelProvider.php

If you encounter an error when accessing your panel, ensure that the service provider is registered in bootstrap/providers.php (for Laravel 11 and above) or config/app.php (for Laravel 10 and below). If it isn’t, you’ll need to add it manually.

Create a User

Next step is creating a user to access this panel. But, before running the create user command, check the following laravel configuration and update the configuration as per the requirements,

  • Add Database credentials to .env file.
  • Run the following command to run the migration. It will create users table into the database.
    php artisan migrate

Run the following command to create a user after checking above requirements,

php artisan make:filament-user

It will ask some basic questions like name, email, password, etc. for creating a user.

After creating a user, run php artisan serve, open http://127.0.0.1:8000/admin in your web browser, sign in using the created user credentials, and start building your app!