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=customThe 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.