Trying to get FileUpload component to clear after submitting the form

Hi, So, I'm familiar working with php and laravel in general but I'm new to using Filament. That said I have been managing to get by until I ran into this issue. I am creating a widget which shows a file upload field so that I can easily upload a file to be processed by a job later. I've managed to get a form into the widget and the form submission works. I then also added the ability for the form to auto submit when the file is uploaded. So far so good. The problem is that I want the form to clear the file upload ready to take another submission once the form has completed submitting. The problem I'm having is that the reset will work correctly for the first file uploaded, but any subsequent uploads (without a full page refresh) will not reset the field. I have checked what is being returned on save and it's returning blank data for the file field which is what I would expect, however this seems to have no effect beyond the first submission and I haven't managed to find any way to fix this so far. Here is my current code for this:
<?php

namespace App\Filament\Widgets;

use Filament\Forms\Components\FileUpload;
use Filament\Schemas\Concerns\InteractsWithSchemas;
use Filament\Schemas\Contracts\HasSchemas;
use Filament\Widgets\Widget;
use Filament\Schemas\Schema;
use Filament\Notifications\Notification;

class UploadTournamentFileWidget extends Widget implements HasSchemas
{
use InteractsWithSchemas;

protected array $acceptedTypes = ['application/xml', 'text/xml'];

public ?array $data = [];

protected string $view = 'filament.widgets.upload-tournament-file-widget';

public function mount(): void {
$this->form->fill();
}

public function form(Schema $schema): Schema {
return $schema->components([
FileUpload::make('kts')
->id('kts')
->label('Tournament File')
->directory('kts')
->moveFiles()
->acceptedFileTypes($this->acceptedTypes)
])->statePath('data');
}

public function save(): void {
$state = $this->form->getState();
$this->form->fill();

Notification::make()
->title('Uploaded successfully<br><br><strong>File</strong>: '.$state['kts'])
->success()
->send();
}
}
<?php

namespace App\Filament\Widgets;

use Filament\Forms\Components\FileUpload;
use Filament\Schemas\Concerns\InteractsWithSchemas;
use Filament\Schemas\Contracts\HasSchemas;
use Filament\Widgets\Widget;
use Filament\Schemas\Schema;
use Filament\Notifications\Notification;

class UploadTournamentFileWidget extends Widget implements HasSchemas
{
use InteractsWithSchemas;

protected array $acceptedTypes = ['application/xml', 'text/xml'];

public ?array $data = [];

protected string $view = 'filament.widgets.upload-tournament-file-widget';

public function mount(): void {
$this->form->fill();
}

public function form(Schema $schema): Schema {
return $schema->components([
FileUpload::make('kts')
->id('kts')
->label('Tournament File')
->directory('kts')
->moveFiles()
->acceptedFileTypes($this->acceptedTypes)
])->statePath('data');
}

public function save(): void {
$state = $this->form->getState();
$this->form->fill();

Notification::make()
->title('Uploaded successfully<br><br><strong>File</strong>: '.$state['kts'])
->success()
->send();
}
}
And this is the blade file:
<x-filament-widgets::widget>
<x-filament::section>
<div>
<form wire:submit="save">
{{ $this->form }}
</form>

<x-filament-actions::modals />
</div>
</x-filament::section>
</x-filament-widgets::widget>

@script
<script>
document.addEventListener('FilePond:processfiles', (e) => {
@this.save()
});
</script>
@endscript
<x-filament-widgets::widget>
<x-filament::section>
<div>
<form wire:submit="save">
{{ $this->form }}
</form>

<x-filament-actions::modals />
</div>
</x-filament::section>
</x-filament-widgets::widget>

@script
<script>
document.addEventListener('FilePond:processfiles', (e) => {
@this.save()
});
</script>
@endscript
Any help would be appreciated. 🙂
5 Replies
dvarilek
dvarilek5d ago
I might be misunderstanding your issue, but I think you need to reset the $componentFileAttachments property on the livewire component. Filament stores temporary uploaded files there so it is probably being persisted across requests even after submission. In save():
$this->componentFileAttachments = []
$this->componentFileAttachments = []
xcensui
xcensuiOP5d ago
Hi, I've given that a try and unfortunately it behaves the same way. The first time it saves it will clear the second (and subsequent) time it doesn't. I know that the form fill is doing what it's supposed to in that the returned data from the livewire update has a blank value...It's just the FileUpload part seems to ignore that after one go.
dvarilek
dvarilek5d ago
That's weird, I'm honestly not really sure why that happens in the first place. I'm just taking a wild guess, but it might be something to do with the event listener you have there, Try removing it and make the FileUpload ->live() and add this method (you don't need to call it anywhere):
public function updatedData($data)
{
// Your `save()` method contents
}
public function updatedData($data)
{
// Your `save()` method contents
}
xcensui
xcensuiOP5d ago
So, I've given that a try (and learned that live is a thing for FileUpload at the same time :P) That said, this actually made things slightly worse. It submits, which is good...But it now doesn't reset at all. I do appreciate the suggestions though. At this point I'm wondering if it might just be better to send a browser event when it saves and just try to reset the filepond instance manually.
LeandroFerreira
remove your js and try using alpine
<x-filament-widgets::widget>
<x-filament::section>
<div x-data="{ data: @entangle('data'), init() {
$watch('data.kts', value => {

const file = Object.values(value)[0] ?? null;

if(file) {
if(file.startsWith('livewire-file:')) {
$wire.save();
} else {
this.data.kts = {};
}
}
})
} }">
<form wire:submit="save">
{{ $this->form }}
</form>

<x-filament-actions::modals/>
</div>
</x-filament::section>
</x-filament-widgets::widget>
<x-filament-widgets::widget>
<x-filament::section>
<div x-data="{ data: @entangle('data'), init() {
$watch('data.kts', value => {

const file = Object.values(value)[0] ?? null;

if(file) {
if(file.startsWith('livewire-file:')) {
$wire.save();
} else {
this.data.kts = {};
}
}
})
} }">
<form wire:submit="save">
{{ $this->form }}
</form>

<x-filament-actions::modals/>
</div>
</x-filament::section>
</x-filament-widgets::widget>

Did you find this page helpful?