Search code examples
javascriptlaravellaravel-livewire

update Alpinejs binding when Livewire Competent re-renders


I have a livewire form that user-selected date then shows available timeslots for that date via a select options box.

So when the user selects add to cart I just need to past the id of the timeslot. I'm trying to reduce the ajax calls therefore I was wanting to just use AlphineJS binding.

My livewire blade code.

<div class="col-span-6" x-data="{ selectedSession: $el.querySelector('option').value }">
        <label for="session" class="block text-sm text-gray-700 font-semibold">Select Time</label>
        <select id="session" x-model="selectedSession" name="session">
           @foreach ($sessionsForDay as $session)
             <option :value="{{ $session->id }}" value="{{ $session->id }}"  @if ($loop->first) Selected @endif>
                {{ $session->name() }} - 
             </option>
           @endforeach
        </select>
        <p x-text="selectedSession"></p>
    </div>

On page load everything is fine. x-data is getting the currently selected (first) value but when livewire updates $sessionsForDay and re-renders the options fields, AlpineJS doesn't update the id and will show the old ID. If I then select a new time it will then update.

I know livewire has a JS hook but just doesn't feel like the best way for something so simple.


Solution

  • Since you're using Livewire, I wouldn't worry about your ajax calls. Livewire handles them very well.

    Anyhow, how is $sessionForDay getting updated by Livewire? There is no direct bind to it, since you're using Alpine's x-model and not Livewire's wire:model. If you had been using a full Livewire code, I would have suggested @entangle.

    Since you are using Alpine, your code is fine for it to work. Alpine has an onchange for the select, and will update the x-model value based on the selected option. You don't need the :value attribute on the option tag, and you don't need the selector on your x-data tag.

    <div class="col-span-6" x-data="{ selectedSession: '{{$sessionsForDay->first()->id}}' }">
        <label for="session" class="block text-sm text-gray-700 font-semibold">Select Time</label>
        <select id="session" x-model="selectedSession" name="session">
           @foreach ($sessionsForDay as $session)
             <option value="{{ $session->id }}"  @if ($loop->first) selected @endif>
                {{ $session->name() }} - 
             </option>
           @endforeach
        </select>
        <p x-text="selectedSession"></p>
    </div>