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 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)

class="max-w-sm mx-auto mb-5" wire:submit.prevent="submit">
         for="countries" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Select an option
         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">
             selected>Choose a country
             value="US">United States
             value="CA">Canada
             value="FR">France
             value="DE">Germany
        

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

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

    




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

  $(document).ready(function (){
        // init_select2();
    });

Livewire Component (Example.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

<span class="na">src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js">
 href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet" />
<span class="na">src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js">

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

expected result without 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();

failed result binding

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 (Example.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 Componenet (example.blade.php

class="max-w-sm mx-auto mb-5" wire:submit.prevent="submit">
         for="countries" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Select an option
         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">
             selected>Choose a country
             value="US">United States
             value="CA">Canada
             value="FR">France
             value="DE">Germany
        

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

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

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

    




    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")
    })

🔍 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! 🚀

here the result

final result


🎯 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.

If you run into issues, try this approach and let me know how it works for you! 🚀🔥