phpjquerylaraveljquery-select2laravel-livewire

Multiple select using select2 in Livewire 3


I want to create multiple selects using the select2 plugin in the livewire component, but the first time I do select "onchange", my select2 disappears into a regular select option. I've used wire:ignore to keep my select element from re-rendering, but it still doesn't work.

Here is my blade component.

    <div wire:ignore>
      <select class="select2" name="named[]" wire:model="named" multiple="multiple">
               @foreach ($jobs as $job)
                    <option value="{{ $job->id }}">{{ $job->name }}</option>
               @endforeach
      </select>
    </div>



<script>
loadContactDeviceSelect2 = () => {
        $('.select2').select2().on('change',function () {
            var value = $(this).val();
            console.log(value);
            @this.dispatchTo('ticket', 'selectedItemChange',value);
        });
        }
        loadContactDeviceSelect2();
        @this.on('loadContactDeviceSelect2',()=>{
        console.log('Event loadContactDeviceSelect2 triggered');
        loadContactDeviceSelect2();
        });
</script>

##and here is my livewire component##

class Ticket extends Component
{
public $named = [];
public $listeners = [
        'selectedItemChange',
    ];

public function save()
    {
if (is_string($this->named)) {
                $this->named = explode(',', $this->named);
            }

            foreach ($this->named as $userId) {
                DB::table('job_user')->insert([
                    'user_id' => $userId,
                    'job_id' => 2, // Assuming job_id is fixed as 2 in your case
                    'created_at' => Carbon::now(),
                ]);
            }
}

public function hydrate()
    {
        $this->dispatch('loadContactDeviceSelect2');
    }
public function selectedItemChange($value)
    {
$this->named = explode(',', $value);
}

public function render()
    {
$jobs = User::all();

        return view('livewire.ticket', ['jobs' => $jobs]);
}

}

Solution

  • This is a possible solution:

    The view

    <div>
    
        <div wire:ignore>
    
            <select class="select2"
                    wire:model="named"
                    multiple="multiple"
            >
    
                @foreach ($jobs as $job)
                    <option value="{{ $job->id }}">{{ $job->name }}</option>
                @endforeach
    
            </select>
    
        </div>
    
        <script>
    
            document.addEventListener("livewire:initialized", () => {
    
                $(".select2").select2()
    
                             .on("change", function () {
    
                                    const values = $(this).val();
                                    console.log(values);
    
                                    @this.named = values;
                                   // @this.set("named", value); -- use this syntax to emulate wire:model.live
                             });
            });
    
        </script>
    
    <div>
    

    The class

    
    class Ticket extends Component
    {
        public $named;
    
    
        public function save()
        {
            // ---- This is not needed: $named is already an array
            // if (is_string($this->named)) {
            //     $this->named = explode(',', $this->named);
            // }
    
    
            foreach ($this->named as $userId) {
                .....
        }
    
    
        public function render()
        {
            $jobs = User::all();
    
            return view('livewire.ticket', ['jobs' => $jobs]);
        }
    }
    

    wire:model="named" is enough to initialize the select, you don't need to dispatch any event, in the same way, to value the $named variable when the value of select2 changes, the change event handler set on select2 is sufficient