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