'Laravel-livewire multiple select2

I've started using Laravel-Livewire and added a Select2 select box library to one of the components.

The problem is, that component has multiple tabs and when i load the component on the tab with the Select2 input everything works fine:

enter image description here

But if i load the component on other tab, or even change the tab and get back to this tab, the Select2 is not loaded correctly and gets back to a regular multiple select:

enter image description here

Im loading the CSS and JS files on layout so they are loaded every time i get this component..

I even added this script to the components

<script>
   $('.select2').select2();
</script>

in order to force this input to be a select2 but even this script wont work.



Solution 1:[1]

try this

// in component
protected $listeners = [
  'selectedItem'
];

public function hydrate()
{
   $this->emit('loadSelect2Hydrate');
} 

public function selectedItem($value)
{
   dd($value);
}

// in blade script section
<script>
  window.loadSelect2 = () => {
   $('.select2').select2().on('change',function () {
     livewire.emitTo('name-component','selectedItem',$(this).val());

     // or

     // @this.set('propertyName',$(this).val());
   });
  }
  loadSelect2();
  window.livewire.on('loadSelect2Hydrate',()=>{
     loadSelect2();
  });
</script>

Solution 2:[2]

From my personal experience, I found that this solution is appropriate to add and update data

in Component Create

class RoleCreate extends Component
{

    public $name;
    public $permission = [];

    protected $rules = [
        'name' => 'required|min:3|max:30|unique:roles,name',
        ....
        'permission' => 'required|array',
    ];

    public function create(){

        if ($this->validate()){
            $data = [
                'name'  => $this->name,
                'color'   => $this->color,
            ];
            $role = Role::create($data);

            if (!empty($this->permission)){
                $permissionId = Permission::whereIn('id', $this->permission)->pluck('id');
                $role->permission()->attach($permissionId);
            }

        }

        $this->alert('success', __('role.Create Role',['NAME'=>$this->name]));

        $this->emit('refreshParent');
        $this->createModalClose();

    }


    public function createModalClose(){
        $this->permission = [];
        $this->reset();
        $this->resetErrorBag();
        $this->resetValidation();
        $this->dispatchBrowserEvent('closeCreateModal');
        $this->dispatchBrowserEvent('cleanData');

    }
    public function render()
    {
        return view('livewire.admin.role.role-create',[
            'permissions' => Permission::all()->pluck('name','id')
        ]);
    }
}

In view create

<div>
    ....

    <div class="w-full">
        <label for="permission"
               class="block mb-2 form-label text-sm font-medium text-gray-900 dark:text-gray-300 @error('permission') text-red-500 dark:text-red-400 @enderror">{{ __('role.Permissions') }}</label>
        <div wire:ignore>
            <select wire:model="permission" class="form-select px-4 py-3 text-gray-900 dark:text-gray-300"
                    style="width: 100% !important;" id="permission" multiple="multiple">
                @foreach($permissions as $key => $value)
                    <option value="{{ $key }}">{{$value}}</option>
                @endforeach
            </select>
        </div>
        @error('permission')
        <span class="mt-2 text-red-500 dark:text-red-400 text-xs">
            {{ $message }}
        </span>
        @enderror
    </div>
    

    @push('css')
        <link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/select2.min.css" rel="stylesheet" />
    @endpush

    @push('scripts')
        <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js" defer></script>
        <script>
            $(document).ready(function() {
                $('#permission').select2({
                    dropdownCssClass: 'text-gray-900 dark:text-gray-600 font-family-is', // you can add name font 
                    selectionCssClass: 'text-gray-900 dark:text-gray-600 font-family-is',
                    placeholder: "{{__('role.Select Permissions')}}",
                });

                $('#permission').on('change', function (e) {
                    @this.set('permission', $(this).val());
                });

                window.addEventListener('cleanData', event => {
                    $('#permission').val('').trigger('change');
                });
            });
        </script>
    @endpush
    
</div>

in Component Update

class RoleUpdate extends Component
{

    public $modelId;
    public $name;
    public $permission = [];


    protected $listeners = [
        'editItemId',
    ];



    protected function rules()
    {
        return [
            'name'=>['required','min:3','max:30','unique:roles,name,'.$this->modelId],
            'permission' => 'required|array',
        ];
    }

    public function editItemId($itemId){
        $this->modelId = $itemId;

        $model = Role::find($this->modelId);
        $this->name         = $model->name;
        $this->permission        = $model->permission->pluck('id');

    }

    public function dehydrate(){
        $this->dispatchBrowserEvent('setDataSelected',['permission' => $this->permission]);

    }


    public function edit(){

        if ($this->validate()){
            $data = [
                'name'  => $this->name,
            ];

           $role = Role::where('id', $this->modelId)->update($data);

            if (!empty($this->permission)){
                $permissionId = Permission::whereIn('id', $this->permission)->pluck('id');
                Role::find($this->modelId)->permission()->sync($permissionId);
            }
        }

        $this->emit('refreshParent');
        $this->closeUpdateModal();

    }

    public function closeUpdateModal(){
        $this->permission = [];
        $this->reset();
        $this->resetErrorBag();
        $this->resetValidation();
        $this->dispatchBrowserEvent('closeUpdateModal');
        $this->dispatchBrowserEvent('cleanData');

    }


    public function render()
    {
        return view('livewire.admin.role.role-update',[
            'permissions' => Permission::all()->pluck('name','id')
        ]);
    }

In view update

<div>
    ...

    <div class="col-span-2">
        <label for="permissionUpdate"
               class="block mb-2 form-label text-sm font-medium text-gray-900 dark:text-gray-300 @error('permission') text-red-500 dark:text-red-400 @enderror">{{ __('role.Permissions') }}</label>
        <div wire:ignore>
            <select wire:model="permission" class="form-select px-4 py-3 text-gray-900 dark:text-gray-300"
                    style="width: 100% !important;" id="permissionUpdate" multiple="multiple">
                @foreach($permissions as $key => $value)
                    <option value="{{ $key }}">{{$value}}</option>
                @endforeach
            </select>
        </div>
        @error('permission')
        <span class="mt-2 text-red-500 dark:text-red-400 text-xs">
            {{ $message }}
        </span>
        @enderror
    </div>

    @push('scripts')
        <script src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
        <script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/select2.min.js" defer></script>
        <script>
            $(document).ready(function() {

                window.addEventListener('setDataSelected', event => {
                    $('#permissionUpdate').select2({
                        dropdownParent: $('#updateModal'),
                        dropdownCssClass: 'text-gray-900 dark:text-gray-600 font-family-is',
                        selectionCssClass: 'text-gray-900 dark:text-gray-600 font-family-is',
                        placeholder: "{{__('role.Select Permissions')}}",
                    }).val(event.detail.permission);
                });


                $('#permissionUpdate').on('change', function (e) {
                @this.set('permission', $(this).val());
                });

                window.addEventListener('cleanData', event => {
                    $('#permissionUpdate').val('').trigger('change');
                });

            });
        </script>
    @endpush
    
</div>

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Abdulmajeed