I didn't find a good, simple example where I could reuse multi select with choice.js for my component. That's why I decided to write my own. I do some manipulations with options and wire:change due to a weird interaction between livewire and choice, similar issue is still hanging open in the repository https://github.com/Choices-js/Choices/issues/943
Make blade component
php artisan make:component MultiSelect --view
@props(['options' => [], 'placeholderValue' => '', 'model'])
@php
$uniqId = 'select' . uniqid();
@endphp
<div wire:ignore
x-data
x-init="
$nextTick(() => {
const choices = new Choices($refs.{{ $uniqId }}, {
removeItems: true,
removeItemButton: true,
placeholderValue: '{{ $placeholderValue }}',
})
})"
>
<select
x-ref="{{ $uniqId }}"
wire:change="$set('{{ $model }}', [...$event.target.options].map(option => option.value))"
{{ $attributes }}
multiple
>
@foreach($options as $option)
<option value="{{ $option }}">{{ $option }}</option>
@endforeach
</select>
</div>
@pushOnce('styles')
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/choices.js/public/assets/styles/choices.min.css"/>
@endPushOnce
@pushOnce('scripts')
<script src="https://cdn.jsdelivr.net/npm/choices.js/public/assets/scripts/choices.min.js"></script>
@endPushOnce
And then you can reuse it in a component
<x-multi-select
model="some_public_property"
class="select-custom"
placeholderValue="Select all you want"
:options="['foo', 'bar']"
/>
Don't forget to change or add a @stack('styles')
and @stack('scripts')
to your layout. Or if you know that the selects will be all over the site, it might be easier to just add a link to the CDN
Top comments (2)
Here are even better snippets:
So the first piece of code is a better multi-select component which can be used to specify the value to be displayed and information to act as the value of the selected option. Also I have added the capability to select a group of items at once.
The function below is used to gather the values one would be interested at and send to the multi-select component using events. I prefer using events since they good for real time updates. I have declared my variable which is holding the selected options in my form:
public SendToUserForm $form;
Finally on the view:
wire:change="$set('{{ $model }}', [...$event.target.options].map(option => option.value))"
I think this line should be changed to
wire:change="$set('{{ $model }}', [...$event.target.selectedOptions].map(option => option.value))"
to just get the selected options.