skip to Main Content

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]);
}

}

2

Answers


  1. When livewire re-renders a component you are losing your .select2 initialization, you coul try to move your logic into function and call this function, when loadContactDeviceSelect2 is triggered:

    <script>
    function loadContactDeviceSelect2() {
        $('.select2').select2().on('change', function () {
            var value = $(this).val();
            console.log(value);
            @this.dispatchTo('ticket', 'selectedItemChange', value);
        });
    }
    
    loadContactDeviceSelect2();
    
    Livewire.on('loadContactDeviceSelect2', () => {
        loadContactDeviceSelect2();
    });
    </script>
    
    Login or Signup to reply.
  2. 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

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search