Apps Artificial Intelligence CSS DevOps Go JavaScript Laravel Linux MongoDB MySQL PHP Python Rust Svelte Vue

Building a Live Search Page in Filament PHP

1 min read .
Building a Live Search Page in Filament PHP

Real-time search can make an admin dashboard much easier to use. Filament is built on Livewire, so a custom resource page can react to search input without writing a separate frontend application.

This example adds a live-search page to a PostResource.

1. Generate a Custom Page

Generate a custom page inside the resource:

php artisan make:filament-page SearchPost --resource=PostResource --type=custom

The exact generated path can vary by Filament version and panel structure, so check the files created by the command.

2. Register the Page

In app/Filament/Resources/PostResource.php, add the page to getPages() alongside the resource’s existing routes:

class PostResource extends Resource
{
    public static function getPages(): array
    {
        return [
            // Keep the resource's existing index/create/edit pages here.
            'search' => Pages\SearchPost::route('/search'),
        ];
    }
}

The custom page then becomes part of the resource’s route group.

3. Implement Live Search Logic

In the generated SearchPost page class:

use App\Filament\Resources\PostResource;
use App\Models\Post;
use Filament\Resources\Pages\Page;

class SearchPost extends Page
{
    protected static string $resource = PostResource::class;
    protected static string $view = 'filament.resources.post-resource.pages.search-post';

    public string $query = '';

    public function getPostsProperty()
    {
        $query = trim($this->query);

        if ($query === '') {
            return collect();
        }

        return Post::query()
            ->where('title', 'like', '%' . $query . '%')
            ->limit(20)
            ->get();
    }
}

Using a computed Livewire property avoids copying model data into a public array every time the input changes. Returning no results for an empty query also prevents loading the entire table accidentally.

For large datasets, add an appropriate database index and consider full-text search or a dedicated search engine rather than relying on a leading-wildcard LIKE query.

4. Build the Blade View

Create or update the generated Blade view:

<x-filament-panels::page>
    <x-filament::input.wrapper>
        <x-filament::input
            type="search"
            wire:model.live.debounce.300ms="query"
            placeholder="Search post titles..."
        />
    </x-filament::input.wrapper>

    <div class="mt-6 space-y-4">
        @forelse ($this->posts as $post)
            <div class="rounded-lg border p-4">
                <h3 class="text-lg font-semibold">{{ $post->title }}</h3>
                @if ($post->description)
                    <p class="text-sm text-gray-600">{{ $post->description }}</p>
                @endif
            </div>
        @empty
            @if (trim($query) !== '')
                <p>No matching posts found.</p>
            @endif
        @endforelse
    </div>
</x-filament-panels::page>

wire:model.live.debounce.300ms updates the server-side property after a short pause in typing, reducing unnecessary requests while still feeling responsive.

Conclusion

A Filament custom page plus Livewire is enough to build a responsive live-search experience inside an admin panel. Start with a small debounced query, limit the result set, and upgrade the search strategy as the data volume and matching requirements grow.

Related Posts

chevron-up