Search code examples
laravel-livewire

Livewire model value for a specific row is not showing after mount


I have different spots for different rows/stations(didn't put the whole table for length reasons)and I want to have a live update of the values. They go into a pivot table and the edit works, but I am not sure how to also display the spots that are already in the database. They seem to appear for a split second when refreshing, but then they disappear, and also, when I try to edit multiple rows I am not sure how to empty the array such that it won't have the previous value without messing with the rest of the spots.

@foreach($selected_stations as $key => $selected_station)
<td class="border px-4 py-2">
                    <input name="spot[{{$selected_station->id}}]"  wire:model="spot.{{$selected_station->id}}" wire:change="updatespot({{$selected_station->id}})" type="text" class="appearance-none block w-full bg-gray-200 text-gray-700 border border-gray-200 rounded py-3 px-4 leading-tight focus:outline-none focus:bg-white focus:border-gray-500" value="{{$current_workbook->stations()->find($selected_station->id)->pivot->spot}}">
</td>
@endforeach

This is from my livewire component

public $spot;
public $spot_value;
public $selected_stations;
public $current_workbook;

public function mount($client, $workbook){
        $this->selected_stations= $workbook->stations;
        $this->current_workbook = Workbook::find($this->workbook_id);
        foreach($this->selected_stations as $key => $selected_station){
            $this->spot = $this->current_workbook->stations()->find($selected_station->id)->pivot->spot;
        }

    }
public function updatespot(Request $request, $station_id){
        $this->spot_value = implode(", ", $this->spot);
        // dd($this->spot_value);
        $this->current_workbook->stations()->updateExistingPivot($station_id, ['spot'=>$this->spot_value]);
    }

And this is the error that shows because I am not clearing the array

Warning: 1265 Data truncated for column 'spot' at row 1 (SQL: update station_workbook set spot = 99, 45, updated_at = 2021-08-11 19:56:10 where station_workbook.workbook_id = 47 and station_id in (18))


Solution

  • You should only really need the wire:model attribute in the frontend to enable you to render/update the spots values. Here's a simplified component example:

    public $workbook;
    public $stations;
    public $spots;
    
    public function mount($workbook)
        $this->stations= $workbook->stations;
        
        // This will give you an array of spots keyed by station id
        $this->spots = $this->stations->pluck('pivot.spot', 'id')->all();
    }
    
    // ...
    
    /**
     * Here we leverage a Livewire Lifecycle hook to
     * detect when our $spots variable has been updated.
     * 
     * This helpfully passes us the new value and the
     * corresponding key, in this case our station id
     */
    public function updatedSpots($value, $key){
        $this->workbook->stations()
            ->updateExistingPivot($key, ['spot' => $value]);
    }
    

    So how does this work in the frontend? All we need on our inputs is the wire:model attribute bound to the specific key in our $spots array:

    @foreach($stations as $station)
        <td class="border px-4 py-2">
            <input type="text" wire:model="spots.{{ $station->id }}" class="...">
        </td>
    @endforeach
    

    This updates in realtime for each input. Livewire has a built in debounce of 150ms for wire:model, but can increase the delay on that to minimise the requests to your database:

    <input type="text" wire:model.debounce.500ms="spots.{{ $station->id }}" class="...">