Reputation: 39
I am trying to update a table with spots. I wanted to do it on click with livewire but nothing worked so I figured it would be easier to just use the methods in the Laravel controller that I already had. The attach and detach are used because I have two tables in my view, one with all the stations and the other one, the one I am trying to update, with the stations that are already in a workbook. With the way I have my method right now I can update everything except for the spot and I am not sure why. It is a many to many relationship between the workbooks and stations and spots are an extra field in the pivot table.
<form action="{{route('admin.workbooks.update', [$client_id, $workbook_id])}}" method="POST" enctype="multipart/form-data">
@csrf
@method('PUT')
<div class="form-group">
<label for="">Media Schedule Name</label>
<input type="text" class="form-control" name="wrkb_name" value="{{$workbook_name}}">
</div>
<table class="table-auto w-full mb-6">
<thead>
<tr>
<th class="px-4 py-2"></th>
@if($showLetter)
<th wire:click="sortBy('call_letter')" style="cursor: pointer;" class="px-4 py-2">Call Letter @include('partials.sort-icon',['field'=>'call_letter'])</th>
@endif
<th style="cursor: pointer;" class="px-4 py-2">Spots @include('partials.sort-icon',['field'=>'spots'])</th>
</tr>
</thead>
<tbody>
@foreach($selected_stations as $key => $selected_station)
<tr>
<td class="border px-4 py-2">
<input name="selected_stations[]" wire:model="selected_already" value="{{ $selected_station->id }}" type="checkbox">
</td>
@if($showLetter)
<td class="border px-4 py-2">{{$selected_station->call_letter}}</td>
@endif
<td class="border px-4 py-2">
<input name="spot" 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="{{$selected_station->pivot->spot}}" placeholder="{{$selected_station->pivot->spot}}"></td>
<td>
</td>
</tr>
@endforeach
</tbody>
</table>
<br>
<table class="table-auto w-full mb-6">
<thead>
<tr>
<th class="px-4 py-2"></th>
@if($showLetter)
<th wire:click="sortBy('call_letter')" style="cursor: pointer;" class="px-4 py-2">Call Letter @include('partials.sort-icon',['field'=>'call_letter'])</th>
@endif
</tr>
</thead>
<tbody>
@foreach($stations as $key => $station)
<tr>
<td class="border px-4 py-2">
<input name="stations[]" wire:model="selected" value="{{ $station->id }}" type="checkbox">
</td>
@if($showLetter)
<td class="border px-4 py-2">{{$station->call_letter}}</td>
@endif
<td>
</td>
</tr>
@endforeach
</tbody>
</table>
@else
<p class="text-center">Whoops! No users were found 🙁</p>
@endif
<div class="w-full flex pb-10" >
<div class="w-1/6 relative mx-1 space-x-6">
<button class="block appearance-none w-full bg-black border border-gray-200 text-white py-3 px-4 pr-8 rounded leading-tight focus:outline-none focus:bg-white focus:border-gray-500">Edit Media Schedule</button>
</div>
</div>
</form>
public function update(UpdateWorkbookRequest $request,Client $client, Workbook $workbook)
{
$workbook->update($request->only('wrkb_name'));
$workbook->stations()->detach($request->input('selected_stations', []));
$workbook->stations()->attach($request->input('stations', []));
$workbook->stations()->updateExistingPivot('spot', []);
return redirect()->route('admin.workbooks.edit', [$client->id, $workbook->id])->with('success', 'Successfully Edited the Workbook');
}
This is how one of the relationship looks like, although I don't think this helps much
public function workbooks()
{
return $this->belongsToMany(\App\Models\Workbook::class, 'station_workbook', 'station_id', 'workbook_id')->withPivot('spot')->withTimestamps();;
}
I also found that I could use something like this, but I only want to update that specific record and from this code it seems like it updates every instance of that station, no matter what workbook and it doesn't work anyway.
foreach($workbook->stations as $key => $station){
dd($station->workbooks);
$station->workbooks()->updateExistingPivot($key, ['spot' => $request ->spot]);
}
I have also tried this with no success
$usedStations=$request->input('stations', []);
$workbook->update($request->only('wrkb_name'));
$workbook->stations()->detach($request->input('selected_stations', []));
$workbook->stations()->attach($request->input('stations', []));
foreach($usedStations as $usedStation)
{
$station_id = Station::where('id',$usedStation)->value('id');
$workbook->stations()->updateExistingPivot($station_id, ['spot' => $request ->spot]);
}
Upvotes: 0
Views: 355
Reputation: 360
Quoting from Laravel Doc: (Link)
When attaching a relationship to a model, you may also pass an array of additional data to be inserted into the intermediate table
So, you can do :
$workbook->stations()->attach($request->input('stations', []),['spot'=>$request->input('spot')]);
UPDATE
Currently, in your code only single value for 'spot' field is being passed to the request. Change it to:
<input name="spot[{{$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="{{$selected_station->pivot->spot}}" placeholder="{{$selected_station->pivot->spot}}"></td>
update() method should be:
public function update(UpdateWorkbookRequest $request,Client $client, Workbook $workbook)
{
$workbook->update($request->only('wrkb_name'));
$workbook->stations()->detach($request->input('selected_stations', []));
$workbook->stations()->attach($request->input('stations', []));
//take only the spot values of selected_stations that were unchecked
$spots = array_diff_key($request->input('spot',[]), array_flip($request->input('selected_stations',[])));
foreach($spots as $station_id=>$spot_value){
$workbook->stations()->updateExistingPivot($station_id, ['spot'=>$spot_value]);
}
return redirect()->route('admin.workbooks.edit', [$client->id, $workbook->id])->with('success', 'Successfully Edited the Workbook');
}
Upvotes: 1