How to use select2 multiselect with livewire
Asked Answered
D

3

6

What I am trying to achieve is, there are two models A and B with a relationship of One to many, where A has many B. So if the records for A and B have already been created, A can be assigned to many B. So I started this current project with livewire, and now I am at a loss. Normal select with multiple works just fine and populates the array in the backend of livewire. But when I use select2 nothing is stored in the array, and when I dd it, it shows an empty array. Even though livewire provides wonderful set of tools, I am starting to realize that there is a lot of gray areas where things are missing or lacks external support, like select2 here.

Here is what I have done so far:

<div>
<div class="tab-pane fade show active" id="card1" role="tabpanel" aria-labelledby="card1-tab">
    <div class="pt-3"></div>
    <div class="row" >
        <div class="form-group col">
            <label for="cards">Enter Cards</label>
            <select class="form-control select2" id="cards" multiple="multiple" onchange="this.dispatchEvent(new InputEvent('input'))>
                <option disabled="">Select Cards</option>
                @foreach($cardsUnassigned as $card)
                    <option value="{{ $card->id }}">{{ $card->imei_number }}</option>
                @endforeach
            </select>
        </div>
        
        <div class="form-group col">
            <label for="technicians" class="">Technicians</label>
            <select class="form-control select2" id="technicians" wire:model='techies.'>
                <option disabled="">Select Technicians</option>
                @foreach($technicians as $tech)
                    <option value="{{ $tech->id }}">{{ $tech->first_name }}</option>
                @endforeach
            </select>
        </div>
    </div>

    @foreach($cardSelect as $key => $value)
        {{$value}}     
    @endforeach
    <button wire:click="assignCardToTech()" class="btn btn-primary">Submit</button>
</div>
</div>

@push('scripts')

<script>
    
        $('#cards').select2({
            placeholder: 'Select Cards to assign'
        });
        //send data to livewire
        $('#technicians').select2({
            placeholder: 'Select Technicians'
        });

</script>

@endpush

And the backend:

<?php

namespace App\Http\Livewire\Stock\Assigns;

use App\Models\Card;
use App\Models\Sim;
use App\Models\Technician;
use Livewire\Component;
use Livewire\WithPagination;
use Illuminate\Support\Facades\Auth;

class Assigns extends Component
{

    public $sortBy_card = 'imei_number';
    public $sortBy_sim = 'ip';
    public $sortDirection = 'asc';
    public $search = '';
    public $perPage = 10;

    public $cardSelect = [];
    public $techies;

    public function render()
    {

        $simsUnassigned = Sim::query()
        ->whereNull('technician_id')
        ->searchUnassigned($this->search)
        ->get();

        $cardsUnassigned = Card::query()
        ->whereNull('technician_id')
        ->searchUnassignedCard($this->search)
        ->get();
        // dd($cardsUnassigned);

        $simsAssigned = Sim::query()
        ->searchAssigned($this->search)
        ->orderBy($this->sortBy_sim, $this->sortDirection)
        ->paginate($this->perPage);

        $cardsAssigned = Card::query()
        ->searchAssignedCard($this->search)
        ->orderBy($this->sortBy_card, $this->sortDirection)
        ->paginate($this->perPage);

        $technicians = Technician::query()->get();

        return view('livewire.stock.assigns.assigns',compact('simsUnassigned','cardsUnassigned','simsAssigned','cardsAssigned','technicians'))
        ->extends('layouts.base')
        ->section('content');
    }

    public function assignCardToTech(){
        dd($this->cardSelect);
        if($this->cards){
            foreach($this->cards as $card){

            }
        }
    }
}

Hopefully this helps.

Drandell answered 9/3, 2021 at 11:24 Comment(0)
B
5

######## INSIDE LIVEWIRE COMPONENT

public array $locationUsers = [];
protected $listeners = ['locationUsersSelected'];

public function locationUsersSelected($locationUsersValues)
{
  $this->locationUsers = $locationUsersValues;
}

######## INSIDE LIVEWIRE BLADE

<div class="col-md-12 mb-3" wire:ignore>
    <label for="locationUsers">Select Users</label>
    <select id="locationUsers" class="form-control select2" multiple="multiple">
        <option value="">--select--</option>
        @foreach($this->users as $id => $name)
            <option value="{{ $id }}">{{ $name }}</option>
        @endforeach
    </select>
</div>

######## INSIDE LIVEWIRE SCRIPTS

document.addEventListener('livewire:load', function () {
  $('#locationUsers').on('select2:close', (e) => {
    @this.emit('locationUsersSelected', $('#locationUsers').select2('val'));
  });

  $('#locationUsers').val(@this.get('locationUsers')).trigger('change');
});
Brimmer answered 17/5, 2021 at 18:4 Comment(1)
its been a while, I'll test this out and let you know. Thanks for coming up with this code though!Drandell
F
0

Your could try adding this to your html

<div class="form-group col-md-6" wire:ignore>
  <label for="manager" class="mb-0 h5">Assign Managers:</label>
  <select  wire:model="reporting_managers"  id="manager" class="select-2 multiple='multiple' data-placeholder="Assign Managers">
    @foreach ($managers as $manager)
      <option value="{{ $manager->id }}" data-name="{{ $manager->name }}">{{ $manager->name }}</option>
    @endforeach
  </select>
</div>

and then in your javaScript section

$('#manager').on('select2:select', function (e) {
  @this.set('reporting_managers', $('#manager').select2('val'));
});
$('#manager').on('select2:unselect', function (e) {
  @this.set('reporting_managers', $('#manager').select2('val'));
});

This will directly store your selection in variable in livewire and won't get deselected on render.

Featherstitch answered 18/11, 2021 at 7:42 Comment(0)
T
0

Try this onchange="@this.set('yourproperty',$(this).select2('val'))" and property in component public $periode = [];

  <div class="col-md-12 mb-3">
     <label class="form-label">Periode</label>
         <div wire:ignore>
             <select class="form-select periode" multiple onchange="@this.set('periode',$(this).select2('val'))">
                            <option value="">Pilih periode</option>
                 <option value="1">1 Bulan</option>
                 <option value="2">2 Bulan</option>
                 <option value="3">3 Bulan</option>
                 <option value="4">4 Bulan</option>
                 <option value="5">5 Bulan</option>
                 <option value="6">6 Bulan</option>
                 <option value="12">1 Tahun</option>
             </select>
        </div>
    </div>
Thunder answered 7/11, 2023 at 6:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.