Blog yang ditulis Jufi

mendokumentasikan hal yang harus diingat

Fixing Select2 Issues in Laravel Livewire 3: A Frustrating but Solvable Challenge

--

For the past couple of months, I’ve been working on building a simple CMS web app using Laravel with Livewire 3. While everything was going smoothly, I encountered an issue that left me frustrated — my Select2 dropdown wasn’t updating or binding data correctly in Livewire.

📌 Why Use Select2?

I chose Select2 because I needed a simple UI component for searching through a list of data within a dropdown. Select2 provides an elegant solution that enhances standard <select> elements with search functionality, without requiring me to build a custom UI from scratch.

However, integrating Select2 with Livewire 3 wasn’t as straightforward as I expected. The problem? Livewire doesn’t automatically recognize updates made by JavaScript-based components like Select2.

🚨 The Issue: Select2 and Livewire Data Binding

When using Livewire, form inputs are usually bound using wire:model, allowing real-time updates to the component state. However, since Select2 manipulates the DOM using JavaScript, Livewire doesn’t detect changes made by Select2 unless explicitly notified.

here my basic setup

Blade Component (example.blade.php)


<div>
<form class="max-w-sm mx-auto mb-5" wire:submit.prevent="submit">
<label for="countries" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Select an option</label>
<select id="countries" wire:model.live="select_value" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<option selected>Choose a country</option>
<option value="US">United States</option>
<option value="CA">Canada</option>
<option value="FR">France</option>
<option value="DE">Germany</option>
</select>

<input class="mt-2 block mb-2" wire:model="select_value">

<button type="submit" class="text-white bg-blue-700 px-5 py-2 rounded-md">Save</button>

</form>
</div>


<script>
function init_select2(){
var ctr = $('#countries')
ctr.select2();
}

$(document).ready(function (){
// init_select2();
});
</script>bla

Livewire Component (Example.php)

<?php

namespace App\Livewire;

use Livewire\Component;

class Example extends Component
{

public $select_value = "default-value";

public function render()
{
return view('livewire.example');
}

public function submit(){
dd($this->select_value);
}
}

to be able use select2 and jquery, you must include this section on your blade layout

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
<script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"></script>

the code above I do comment on section init select2 and select2 should not be active or running.
here the expected result I need and this is without use select2

you see after click save button I can see result the value I selected. lets turn on and init select2 by uncomment init_select2();

you can see the result still default-value and not binding based on value select we are selected.

✅ The Solution: Manually Dispatching Events to Livewire

Since Livewire 3 doesn’t automatically detect DOM changes from JavaScript-based UI components, we need to manually update Livewire’s state when Select2 changes.

Livewire Component Updated (Example.php)

<?php

namespace App\Livewire;

use Livewire\Attributes\On;
use Livewire\Component;

class Example extends Component
{

public $select_value = "default-value";

public function render()
{
return view('livewire.example');
}

public function submit(){
dd($this->select_value);
}

#[On('select-updated')]
public function updateValue($val){
$this->select_value = $val;
$this->dispatch("update-value");
}
}

Blade Component (example.blade.php)

<div>
<form class="max-w-sm mx-auto mb-5" wire:submit.prevent="submit">
<label for="countries" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Select an option</label>
<select id="countries" wire:model="select_value" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<option selected>Choose a country</option>
<option value="US">United States</option>
<option value="CA">Canada</option>
<option value="FR">France</option>
<option value="DE">Germany</option>
</select>

<input class="mt-2 block mb-2" wire:model="select_value">

<p class="block text-sm mb-2">value selected: {{ $select_value }}</p>

<button type="submit" class="text-white bg-blue-700 px-5 py-2 rounded-md">Save</button>

</form>
</div>

<script>

function init_select2(){
var ctr = $('#countries')
ctr.select2();
}

$(document).ready(function (){
init_select2();
$('#countries').on("change", function (e){
window.Livewire.dispatch('select-updated', [$(this).val()]);
});
});

Livewire.on("update-value", function (){
setTimeout(init_select2, 0)
console.log("event udpated and reset select2")
})

</script>

🔍 Key Fixes & Takeaways

Manually dispatch the select-updated event when Select2 changes.
Listen for update-value in Livewire to trigger a reinitialization of Select2.
Use setTimeout(init_select2, 0); to prevent Select2 from breaking after a Livewire re-render. setTimeout is needed because it ensures that Livewire processes its updates first before re-initializing Select2.

Now, every time a user selects an option, Livewire correctly updates its state, and Select2 remains functional after re-renders! 🚀

🎯 Final Thoughts

Integrating Select2 with Livewire 3 can be frustrating, but the solution is simple once you understand how Livewire handles JavaScript-based components. By manually dispatching updates and re-initializing Select2, you can enjoy the benefits of Livewire’s reactivity and Select2’s powerful search features.

--

--

Jufianto Henri
Jufianto Henri

Written by Jufianto Henri

Mendokumentasikan segala sesuatu yang dibuat kedalam tulisan yang tidak jelas

No responses yet