Livewire issue with V3
Hi all,
I'm trying to understand why one of my edit routes is failing to update the model instance after upgrading from livewire V2 to livewire V3.
The issue is that when I use the edit route to modify an existing $resource, not all of the properties make it into request()-> in the update route when I submit the form.
The model properties outside of the livewire component are updated fine (eg. name and is_published) but the properties handled by the livewire component do not change the model (eg. file and remove_file).
Couple of notes:
- if I downgrade livewire to v2, it works with no code changes
- toggling
legacy_model_bindingtotruein config/livewire.php has no effect, even after clearing caches - I realise my setup might seem unusual/convoluted, having a livewire component included inside a regular blade file, but I have always done this in my projects without issue - is this no longer supported in livewire 3?
The model class in this instance is called "Resource". Below is a copy of the minimum applicable code, with web route -> controller file -> blade component -> livewire component & blade template.
In my testing, I am trying to click the button in file-attachment.blade.php wired to the removeFile() livewire method in FileAttachment.php, and I expect to see the input in file-attachment.blade.php that is wired to remove_file
update to true (which it is, with both V2 and V3) and then get passed back to the update() route in AdminResourceController.php as the remove_file attribute, which works with V2 and fails with V3.
All I need to do to make things work is downgrade to V2, which I am prepared to run with, but I'd like to use V3 if I can work out what I'm doing wrong.
If anyone can shed some light on how this should work that would be appreciated!
in web.php
Route::middleware()->name('admin.')->group(fn() => Route::resource('admin/resources', AdminResourceController::class)->except('show'));
in AdminResourceController.php
public function edit(Resource $resource)
{
$this->authorize('edit', $resource);
return view('admin.resources.edit', [
'resource' => $resource,
]);
}
public function update(Request $request, Resource $resource)
{
$strPath = 'Resource/'.$resource->id.'/file';
$this->authorize('update', $resource);
$attributes = $this->validateResource($resource);
$attributes['is_published'] = request()->has('is_published');// this attribute is modified from outside the livewire component and is successfully updated
// remove file if requested
if (request()->has('remove_file') && request()->remove_file && $resource->exists) {// this attribute is modified from within the livewire component and is not updated
dd('we never make it here');
}
$resource->update($attributes);
return redirect(route('admin.resources.index'))->with('success-resource-updated', $resource->name);
}
protected function validateResource(?Resource $resource = null): array
{
$resource ??= new Resource();
return request()->validate([
'name' => 'required',
'description' => '',
'u_r_l' => '',
'local_path' => '',
'notes' => '',
'file' => 'file',
]);
}
in admin/resources/edit.blade.php
<x-admin-layout>
...
<x-resource method="edit" :resource="$resource"/>{{-- pass in the model instance $resource --}}
...
</x-admin-layout>
in resource.blade.php
@php use App\Models\Resource; @endphp
@props(['method' => 'create'/* create, edit */, 'resource' => $resource??new Resource()])
<form method="post" action="{{ ($method == 'create' ? '/admin/resources' : '/admin/resources/'.$resource->id) }}"
enctype="multipart/form-data"
x-data="{ buttonDisabled: false }" x-on:submit="buttonDisabled = true">
@csrf
@method($method == 'create' ? 'POST' : 'PATCH')
...
<livewire:admin.file-attachment :resource="$resource"/>{{-- pass in model instance $resource --}}
...
</form>
in FileAttachment.php
namespace App\Livewire\Admin;
use App\Models\Resource;
use Livewire\Component;
class FileAttachment extends Component
{
public Resource $resource;
public string $strPath;
public $remove_file = null;
public function mount(Resource $resource)
{
$this->resource = $resource;
$this->strPath = 'Resource/'.$this->resource->id.'/file';
}
public function render()
{
return view('livewire.admin.file-attachment');
}
public function removeFile()
{
$this->resource->file = '';// has no effect on the contents of $resource->file
$this->resource->name .= '#';// this has no effect on the contents of $resource->name
$this->remove_file = true;// this property does not make it to AdminResourceController.php as an attribute value in routes
}
}
in file-attachment.blade.php*
<div x-show="!isURL" x-transition:enter="transition ease-out duration-300"
x-transition:enter-start="opacity-10 translate-x-6"
x-transition:enter-end="opacity-100">
{{--hidden fields--}}
<x-form.admin.input type="hidden" name="remove_file" wire:model="remove_file"/>
{{--file--}}
<x-form.admin.input type="file" name="file" accept="image/png, image/jpeg"
:value="old('file', $resource->file)">File
</x-form.admin.input>
<x-form.button wire:click="removeFile()">Remove File</x-form.button>
{{--test--}}
<input type="text" wire:model="remove_file"/>{{-- so I can see the value "true" when I have successfully removed the file attachment --}}
</div>
Please or to participate in this conversation.