Skip to content

Instantly share code, notes, and snippets.

@saurabh85mahajan
Last active April 8, 2026 12:43
Show Gist options
  • Select an option

  • Save saurabh85mahajan/a21a9673acdeedca063475207202a698 to your computer and use it in GitHub Desktop.

Select an option

Save saurabh85mahajan/a21a9673acdeedca063475207202a698 to your computer and use it in GitHub Desktop.
Select2 with Alpine
@props(['field', 'options', 'selected' => ''])
<div {{ $attributes->merge(['class' => 'mt-4 flex-1']) }} x-data="data()" x-init="setInitial({{$selected}})">
<input type="hidden" :value="selected.value" name="{{$field}}">
<x-input
class="w-1/2"
type="search"
x-model="search"
placeholder="Click to search..."
@click="showOptions"
@search="clearSearch"
/>
<div class="relative" x-show="optionsVisible" @click.away="hideOptions">
<div class="absolute z-50 border p-2 w-1/2 overflow-y-scroll bg-gray-200 max-h-60 grid">
<template x-for="option in filteredOptions()">
<a
@click.prevent="selectOption(option)"
x-html="highlight(option.label)"
class="cursor-pointer hover:bg-blue-200 px-2">
</a>
</template>
</div>
</div>
<script>
function data() {
return {
optionsVisible: false,
search: "",
selected: {
label: "",
value: ""
},
clearSearch() {
this.selected.value = '';
this.selected.label = '';
},
setInitial(selected) {
selectedOption = this.options.find((option) => {
return option.value == selected
});
if(selectedOption != undefined) {
this.selectOption(selectedOption);
}
},
showOptions() {
this.optionsVisible = true;
},
hideOptions() {
this.optionsVisible = false;
},
selectOption(option) {
this.selected = option;
this.hideOptions();
this.search = option.label
},
options: {!! $options->map(function($option, $key) {
return [
'label' => $option,
'value' => $key,
];
})->values() !!},
filteredOptions() {
return this.options.filter((option, i) => {
return option.label.toLowerCase().includes(this.search.toLowerCase());
});
},
highlight(value) {
var text = this.search.trim();
if(text == '') {
return value;
}
var query = new RegExp(`(${text})`, "ig");
return value.replace(query, '<span class="font-extrabold text-blue-600">$1</span>');
}
};
}
</script>
@med-chh
Copy link
Copy Markdown

med-chh commented Jan 23, 2024

good

@danieltorres1109
Copy link
Copy Markdown

Without a script:

`
@props(['label', 'name', 'placeholder', 'options', 'selected' => ''])

merge(['class' => 'mt-4 flex-1']) }} x-data='{ optionsVisible: false, search: "", selected: { label: "", value: "" }, options: @JSON($options), clearSearch() { this.selected.value = ""; this.selected.label = ""; this.search = ""; }, setInitial(selected) { let selectedOption = this.options.find(option => option.value == selected); if (selectedOption !== undefined) { this.selectOption(selectedOption); } }, showOptions() { this.optionsVisible = true; }, hideOptions() { this.optionsVisible = false; }, selectOption(option) { this.selected = option; this.hideOptions(); this.search = option.label; }, filteredOptions() { return this.options.filter(option => option.label.toLowerCase().includes(this.search.toLowerCase())); }, highlight(value) { let text = this.search.trim(); if (text === "") { return value; } let query = new RegExp("(" + text + ")", "ig"); return value.replace(query, "$1"); } }' x-init="setInitial('{{ $selected }}')"> {{ $label }}

`

And the data like:
$zones = Zone::where('is_active', true)->get()->map(function ($zone) {
return [
'label' => $zone->name,
'value' => $zone->id,
];
})->toArray();

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