Multi-select with Alpine.js

How to insert values in wire:model array selected for this example?

<select wire:model="selected" class="hidden" x-cloak id="select">
  @foreach ($stations as $station)
  <option value="{{ $station->id }}">{{ $station->name }}</option>

<div x-data="dropdown()" x-init="loadOptions()" class="w-full md:w-1/2 flex flex-col items-center h-64 mx-auto">
  <input name="values" type="hidden" x-bind:value="selectedValues()">
  <div class="inline-block relative w-64">
    <div class="flex flex-col items-center relative">
      <div x-on:click="open" class="w-full">
        <div class="my-2 p-1 flex border border-gray-200 bg-white rounded">
          <div class="flex flex-auto flex-wrap">
            <template x-for="(option,index) in selected" :key="options[option].value">
              <div class="flex justify-center items-center m-1 font-medium py-1 px-1 bg-white rounded bg-gray-100 border">
                <div class="text-xs font-normal leading-none max-w-full flex-initial x-model=" options[option] x-text="options[option].text"></div>
                <div class="flex flex-auto flex-row-reverse">
                  <div x-on:click.stop="remove(index,option)">
                    <svg class="fill-current h-4 w-4 " role="button" viewBox="0 0 20 20">
                      <path d="M14.348,14.849c-0.469,0.469-1.229,0.469-1.697,0L10,11.819l-2.651,3.029c-0.469,0.469-1.229,0.469-1.697,0
                                           C14.817,13.62,14.817,14.38,14.348,14.849z" />

            <div x-show="selected.length == 0" class="flex-1">
              <input placeholder="Select a option" class="bg-transparent p-1 px-2 appearance-none outline-none h-full w-full text-gray-800" x-bind:value="selectedValues()">
          <div class="text-gray-300 w-8 py-1 pl-2 pr-1 border-l flex items-center border-gray-200 svelte-1l8159u">

            <button type="button" x-show="isOpen() === true" x-on:click="open" class="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
              <svg version="1.1" class="fill-current h-4 w-4" viewBox="0 0 20 20">
                <path d="M17.418,6.109c0.272-0.268,0.709-0.268,0.979,0s0.271,0.701,0,0.969l-7.908,7.83
    L17.418,6.109z" />

            <button type="button" x-show="isOpen() === false" @click="close" class="cursor-pointer w-6 h-6 text-gray-600 outline-none focus:outline-none">
              <svg class="fill-current h-4 w-4" viewBox="0 0 20 20">
                <path d="M2.582,13.891c-0.272,0.268-0.709,0.268-0.979,0s-0.271-0.701,0-0.969l7.908-7.83
    " />

      <div class="w-full px-4">
        <div"isOpen()" class="absolute shadow top-100 bg-white z-40 w-full left-0 rounded max-h-select" x-on:click.away="close">
          <div class="flex flex-col w-full overflow-y-auto h-64">
            <template x-for="(option,index) in options" :key="option" class="overflow-auto">
              <div class="cursor-pointer w-full border-gray-100 rounded-t border-b hover:bg-gray-100" @click="select(index,$event)">
                <div class="flex w-full items-center p-2 pl-2 border-transparent border-l-2 relative">
                  <div class="w-full items-center flex justify-between">
                    <div class="mx-2 leading-6" x-model="option" x-text="option.text"></div>
                    <div x-show="option.selected">
                      <svg class="svg-icon" viewBox="0 0 20 20">
                        <path fill="none" d="M7.197,16.963H7.195c-0.204,0-0.399-0.083-0.544-0.227l-6.039-6.082c-0.3-0.302-0.297-0.788,0.003-1.087

  function dropdown() {
                return {
                    options: [],
                    selected: [],
                    show: false,
                    open() { = true },
                    close() { = false },
                    isOpen() { return === true },
                    select(index, event) {

                        if (!this.options[index].selected) {

                            this.options[index].selected = true;
                            this.options[index].element =;

                        } else {
                            this.selected.splice(this.selected.lastIndexOf(index), 1);
                            this.options[index].selected = false
                    remove(index, option) {
                        this.options[option].selected = false;
                        this.selected.splice(index, 1);

                    loadOptions() {
                        const options = document.getElementById('select').options;
                        for (let i = 0; i < options.length; i++) {
                                value: options[i].value,
                                text: options[i].innerText,
                                selected: options[i].getAttribute('selected') != null ? options[i].getAttribute('selected') : false

                            return this.options[option].value;

1 Like

I have the same issue. Anyone?

After some digging in the docs I found out a solution. For anyone that might having the same issue here is what I did:

Modify these two lines:



@click="select(index,$event); $dispatch('input', selectedValues())"
x-on:click.stop="remove(index,option); $dispatch('input', selectedValues())"

Don’t forget to wire these events to your class property that you want to sync. In my case:

In my case I put all these code inside this div ie.

<div wire:model="selected">
      <!-- multi select code-->

That would sync the data with the server.
This is covered in the documentation here:
but also in the screencast here:

In order to initialize the multi-select with data you have to edit the js code. In my case I edit the loadOptions() function and added this code:

if (options[i].getAttribute('selected') != null) {

and also modified the initial
<select x-cloak id="select">
and marked the needed
with the attribute selected=“selected”.