Skip to content

Instantly share code, notes, and snippets.

@jackabox
Last active November 8, 2022 11:10
Show Gist options
  • Star 12 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jackabox/12f885b70eb36649cae8346c2e5393cb to your computer and use it in GitHub Desktop.
Save jackabox/12f885b70eb36649cae8346c2e5393cb to your computer and use it in GitHub Desktop.
Livewire Autocomplete Component
<div class="relative">
<x-label for="account" class="mb-2">Account Name</x-label>
<div class="relative">
<input
type="text"
class="relative w-full bg-white border border-gray-300 rounded-md shadow-sm pl-3 pr-10 py-2 text-left cursor-default focus:outline-none focus:ring-1 focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
placeholder="Search Accounts..."
wire:model="query"
wire:click="reset"
wire:keydown.escape="hideDropdown"
wire:keydown.tab="hideDropdown"
wire:keydown.Arrow-Up="decrementHighlight"
wire:keydown.Arrow-Down="incrementHighlight"
wire:keydown.enter.prevent="selectAccount"
/>
<input type="hidden" name="account" id="account" wire:model="selectedAccountID">
@if ($selectedAccount)
<a class="absolute cursor-pointer top-2 right-2 text-gray-500" wire:click="reset">
<svg xmlns="http://www.w3.org/2000/svg" width="24" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</a>
@endif
</div>
@if(!empty($query) && $selectedAccount == 0 && $showDropdown)
<div class="absolute z-10 bg-white mt-1 w-full border border-gray-300 rounded-md shadow-lg">
@if (!empty($accounts))
@foreach($accounts as $i => $account)
<a
wire:click="selectAccount({{ $i }})"
class="block py-1 px-2 text-sm cursor-pointer hover:bg-blue-50 {{ $highlightIndex === $i ? 'bg-blue-50' : '' }}"
>{{ $account['name'] }}</a>
@endforeach
@else
<span class="block py-1 px-2 text-sm">No results!</span>
@endif
</div>
@endif
</div>
<?php
namespace App\Http\Livewire;
use App\Models\Account;
use Livewire\Component;
class AccountAutocomplete extends Component
{
public $query= '';
public array $accounts = [];
public int $selectedAccount = 0;
public int $highlightIndex = 0;
public bool $showDropdown;
public function mount()
{
$this->reset();
}
public function reset(...$properties)
{
$this->accounts = [];
$this->highlightIndex = 0;
$this->query = '';
$this->selectedAccount = 0;
$this->showDropdown = true;
}
public function hideDropdown()
{
$this->showDropdown = false;
}
public function incrementHighlight()
{
if ($this->highlightIndex === count($this->accounts) - 1) {
$this->highlightIndex = 0;
return;
}
$this->highlightIndex++;
}
public function decrementHighlight()
{
if ($this->highlightIndex === 0) {
$this->highlightIndex = count($this->accounts) - 1;
return;
}
$this->highlightIndex--;
}
public function selectAccount($id = null)
{
$id = $id ?: $this->highlightIndex;
$account = $this->accounts[$id] ?? null;
if ($account) {
$this->showDropdown = true;
$this->query = $account['name'];
$this->selectedAccount = $account['id'];
}
}
public function updatedQuery()
{
$this->accounts = Account::where('name', 'like', '%' . $this->query. '%')
->take(5)
->get()
->toArray();
}
public function render()
{
return view('livewire.account-autocomplete');
}
}
@lucioaguiar
Copy link

Good job, you have to change selectedAccountID to selectedAccount, to show the id when submitting the form.
I have a question, when I type in a name and select, if afterwards I delete the name using the mouse selection, the selected model still continues, how can I fix it?

1º - I type a name.
Screenshot_20210501_111248

2º - I click to select an account and then select the name using the mouse selection and stopping the pointer outside the input box.
Screenshot_20210501_111340

3º - And then I press “delete” or “back space”, to delete, but the account still remains, if I submit the form the Id is still there, how to fix it?
Screenshot_20210501_111359

Thank you very much for the work.

@danielzzz
Copy link

doesn't it put much stress on the server making calls for each keystroke to increase or decrease the highlight counter?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment