Ever built a dropdown that searches a massive database and watched your server slow down with every single keystroke? You need a searchable dropdown that waits until the user finishes typing before making a request.

  • How to set up a Livewire component for searching data
  • Using Alpine.js to handle local UI state without extra page reloads
  • Adding a debounce delay to prevent hammering your database
  • Rendering dynamic search results smoothly

Setting Up the Livewire Component

First, we need a Livewire component that holds our search query and fetches matching users from the database. Run the command to make your component and paste the following backend logic.

namespace App\Livewire;\n\nuse App\Models\User;\nuse Livewire\Component;\n\nclass SearchDropdown extends Component\n{\n    public $search = '';\n    public $selectedUser = null;\n\n    public function render()\n    {(\n        return view('livewire.search-dropdown', [\n            'users' => strlen($this->search) > 1 \n                ? User::where('name', 'like', '%' . $this->search . '%')->take(5)->get() \n                : [],\n        ]);\n    }\n}

This code checks if the user has typed at least two characters before running a database query, limiting the results to five items.

Building the Frontend with Alpine.js and Livewire

Next, we build the view file. We will use Alpine.js to handle opening and closing the dropdown menu based on user interaction.

<div x-data="{ open: false }" class="relative">\n    <input \n        type="text" \n        wire:model.live.debounce.300ms="search" \n        @focus="open = true"\n        @click.away="open = false"\n        placeholder="Search users..." \n        class="border p-2 rounded w-full"\n    >\n\n    <div x-show="open && $wire.users.length > 0" class="absolute bg-white border w-full mt-1 rounded shadow-lg">\n        @foreach($users as $user)\n            <div class="p-2 hover:bg-gray-100 cursor-pointer">\n                {{ $user->name }}\n            </div>\n        @endforeach\n    </div>\n</div>

The wire:model.live.debounce.300ms modifier tells Livewire to wait 300 milliseconds after the user stops typing before sending the search query to the server.

Common mistakes

One common mistake is forgetting to add a minimum character length check before querying the database. If you search on every single keystroke including empty strings, you will return every record and bog down your server. Always check strlen($this->search) > 1 or similar before running your query. Another mistake is omitting the click.away modifier in Alpine, which leaves dropdown menus stuck open on the screen when users click elsewhere.

Clone this repository to your local machine and try adding keyboard navigation with the up and down arrow keys next.