Initialize select2 on select change with alpine js

Viewed 823

I have a form with a select, and on change (and when a certain option is chosen) I would like another select to become visible. That second select uses select2. I use Alpine JS (in Laravel) for that.

The problem is that the second select is not visible on page load and that the query code to initialize the select2 on document ready is not loaded.

When I choose the specific value in the first select, the second select shows, but the width of it is very small.

How can I initialize select2 dynamically?

<div x-data="{vervoerswijze:1}">

  <div class="mt-4">
    <select x-model='vervoerswijze' class="text-gray-500 form-select block w-full mt-1 shadow-sm rounded-md border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
      <option>Kies een optie</option>
      <option value="1">Winkel</option>
      <option value="2">Met gebruiker(s)</option>
    </select>
  </div>

  <div x-show="vervoerswijze == 2" class="mt-4 w-full" wire:ignore>
    <x-jet-label class="text-gray-500 font-normal text-base mb-4" for="Gebruikers" value="{{ __('Selecteer gebruikers') }}" />
    <select wire:model="gebruikerinwagen"  class="select2 text-gray-500 form-select block w-full mt-1 shadow-sm rounded-md border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" multiple="multiple">
      @foreach ($gebruikers as $gebruiker)
        <option value="{{ $gebruiker->id }}">{{ $gebruiker->first }} {{ $gebruiker->last }}</option>
      @endforeach
    </select>
  </div>     
</div> 

<script>
$(function(){
  $('.select2').select2().on('change', function(){
    @this.set('gebruikerinwagen', $(this).val());
  });
})
</script>
1 Answers

You might be able to do the following

<template x-if="vervoerswijze == 2">
  <div class="mt-4 w-full" wire:ignore>
    <x-jet-label class="text-gray-500 font-normal text-base mb-4" for="Gebruikers" value="{{ __('Selecteer gebruikers') }}" />
    <select x-data="initSelect2($el)" wire:model="gebruikerinwagen"  class="select2 text-gray-500 form-select block w-full mt-1 shadow-sm rounded-md border-gray-300 focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50" multiple="multiple">
      @foreach ($gebruikers as $gebruiker)
        <option value="{{ $gebruiker->id }}">{{ $gebruiker->first }} {{ $gebruiker->last }}</option>
      @endforeach
    </select>
  </div>
</template>

<script>
function initSelect2(element) {
  $($element).select2().on('change', function(){
    @this.set('gebruikerinwagen', $(this).val());
  });
}
</script>

The key changes are to:

  • to initialise Select2 when the relevant select is rendered on the page (using Alpine.js x-data)
  • use an x-if (instead of x-show) so that the select is only rendered when necessary (and therefore select2 only gets initialised when necessary)
Related