How to build a search drop down component with Laravel Livewire | Owen Conti

How to build a search drop down component with Laravel Livewire

Published on Aug 21, 2019 in category Laravel.

๐Ÿ“บ There's a video version of this post at the bottom of the page.

Laravel Livewire allows you to build interactive web applications without any custom JavaScript. It's built around the Laravel framework.

Watch the video below for a step-by-step guide on how you can use Laravel Livewire to build an interactive search drop down component, without any custom JavaScript.

Here's the final code:

<?php

namespace App\Http\Livewire;

use App\Contact;
use Livewire\Component;

class ContactSearchBar extends Component
{
    public $query;
    public $contacts;
    public $highlightIndex;

    public function mount()
    {
        $this->reset();
    }

    public function reset()
    {
        $this->query = '';
        $this->contacts = [];
        $this->highlightIndex = 0;
    }

    public function incrementHighlight()
    {
        if ($this->highlightIndex === count($this->contacts) - 1) {
            $this->highlightIndex = 0;
            return;
        }
        $this->highlightIndex++;
    }

    public function decrementHighlight()
    {
        if ($this->highlightIndex === 0) {
            $this->highlightIndex = count($this->contacts) - 1;
            return;
        }
        $this->highlightIndex--;
    }

    public function selectContact()
    {
        $contact = $this->contacts[$this->highlightIndex] ?? null;
        if ($contact) {
            $this->redirect(route('show-contact', $contact['id']));
        }
    }

    public function updatedQuery()
    {
        $this->contacts = Contact::where('name', 'like', '%' . $this->query . '%')
            ->get()
            ->toArray();
    }

    public function render()
    {
        return view('livewire.contact-search-bar');
    }
}
<div class="relative">
    <input
        type="text"
        class="form-input"
        placeholder="Search Contacts..."
        wire:model="query"
        wire:keydown.escape="reset"
        wire:keydown.tab="reset"
        wire:keydown.ArrowUp="decrementHighlight"
        wire:keydown.ArrowDown="incrementHighlight"
        wire:keydown.enter="selectContact"
    />

    <div wire:loading class="absolute z-10 list-group bg-white w-full rounded-t-none shadow-lg">
        <div class="list-item">Searching...</div>
    </div>

    @if(!empty($query))
        <div class="fixed top-0 right-0 bottom-0 left-0" wire:click="reset"></div>

        <div class="absolute z-10 list-group bg-white w-full rounded-t-none shadow-lg">
            @if(!empty($contacts))
                @foreach($contacts as $i => $contact)
                    <a
                        href="{{ route('show-contact', $contact['id']) }}"
                        class="list-item {{ $highlightIndex === $i ? 'highlight' : '' }}"
                    >{{ $contact['name'] }}</a>
                @endforeach
            @else
                <div class="list-item">No results!</div>
            @endif
        </div>
    @endif
</div>


Thanks for reading!

๐Ÿ‘‹ Hi there! I hope you enjoyed this post. If you did, follow me on Twitter, @owenconti, for updates on new posts.

If you prefer to receive updates via email, subscribe to my newsletter where I send a weekly summary of the content I've released.

Feel free to check out other posts in the Laravel category.