Skip to content

Instantly share code, notes, and snippets.

@mithicher
Last active October 25, 2024 19:29
Show Gist options
  • Save mithicher/9944232624cbad4b1cb5d3d2cac87a97 to your computer and use it in GitHub Desktop.
Save mithicher/9944232624cbad4b1cb5d3d2cac87a97 to your computer and use it in GitHub Desktop.
Tom Select Livewire Blade Component
/* Component Usage
// Data for options
$users = \App\User::limit(6)->get()->transform(fn($user) => [
'id' => $user->id,
'title' => $user->name,
'subtitle' => $user->email
]);
// Usage in view
<x-tom-select
id="testUser"
name="testUser"
wire:model="testUser"
:options="$users"
placeholder="Pick a user"
items="{{ $testUser }}" // for multiselect edit eg. 1,2,3 comma separated ids
// multiple // enable for multiple select
/>
*/
@props([
'options' => [],
'items' => null
])
<div wire:ignore>
<select
x-data="{
tomSelectInstance: null,
options: {{ collect($options) }},
items: [{{ $items }}],
renderTemplate(data, escape) {
return `<div class='flex items-center'>
<span class='mr-3 w-8 h-8 rounded-full bg-gray-100'><img src='https://avatars.dicebear.com/api/initials/${escape(data.title)}.svg' class='w-8 h-8 rounded-full'/></span>
<div><span class='block font-medium text-gray-700'>${escape(data.title)}</span>
<span class='block text-gray-500'>${escape(data.subtitle)}</span></div>
</div>`;
},
itemTemplate(data, escape) {
return `<div>
<span class='block font-medium text-gray-700'>${escape(data.title)}</span>
</div>`;
}
}"
x-init="tomSelectInstance = new TomSelect($refs.input, {
valueField: 'id',
labelField: 'title',
searchField: 'title',
options: options,
items: items,
@if (! empty($items) && ! $attributes->has('multiple'))
placeholder: undefined,
@endif
render: {
option: renderTemplate,
item: itemTemplate
}
});"
x-ref="input"
x-cloak
{{ $attributes }}
placeholder="Pick some links..."></select>
</div>
@once
@push('styles')
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/tom-select.css" rel="stylesheet">
<style>
.ts-input {
padding: 10px 8px;
border-radius: 0.5rem;
border-color: rgba(209, 213, 219, 1.0);
box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05);
}
.ts-input.focus {
outline: 2px solid transparent;
outline-offset: 2px;
box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), 0 0 0 3px rgba(199, 210, 254, 0.5);
border-color: rgba(165, 180, 252, 1.0);
}
.ts-input.dropdown-active {
border-radius: 0.5rem 0.5rem 0 0;
}
.ts-dropdown {
margin: -5px 0 0 0;
border-radius: 0 0 0.5rem 0.5rem;
padding-bottom: 4px;
}
.ts-control.single .ts-input:after {
content: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' fill='none' viewBox='0 0 24 24' stroke='%239CA3AF'%3E%3Cpath stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M8 9l4-4 4 4m0 6l-4 4-4-4' /%3E%3C/svg%3E");
display: block;
position: absolute;
top: 10px;
right: 8px;
width: 24px;
height: 24px;
border: none;
}
</style>
@endpush
@push('scripts')
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/tom-select.complete.min.js"></script>
@endpush
@endonce
@CallumCarmicheal
Copy link

Just a lil late, by uhh 2 years. Had a ton of problems, with tom-select but this managed to send me in the correct direction thanks :)

I had written some code to allow for real-time updating of the item list and the selected value so that you can change those in php / server side and have it reflect in the selection.

The fork is here if anyone comes across this and need a more documented and implemented solution https://gist.github.com/CallumCarmicheal/3bcbfb178443c9a11c673be83530ac8d

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