DEV Community

Cover image for Livewire 3 multiple select with choice.js
Vitalik
Vitalik

Posted on

Livewire 3 multiple select with choice.js

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
Enter fullscreen mode Exit fullscreen mode
@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
Enter fullscreen mode Exit fullscreen mode

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']"
/>
Enter fullscreen mode Exit fullscreen mode

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 (1)

Collapse
 
liruxme profile image
David

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.