F
Filament4mo ago
Damien

Why does my form `->required()` methods not work inside of a Livewire component?

Hey all, so I am creating a 'Settings' page which has a collection of livewire components. I am trying to use a Radio input and a File upload input like so:
public function form(Form $form): Form
{
return $form
->schema([
FileUpload::make('attachment')
->previewable(false)
->storeFiles(false)
->downloadable()
->required()
->acceptedFileTypes(['text/csv']),
Radio::make('type')
->label('Type of Products')
->options([
'1' => 'Products',
'2' => 'Services',
])
->required(),
])
->statePath('data');
}
public function form(Form $form): Form
{
return $form
->schema([
FileUpload::make('attachment')
->previewable(false)
->storeFiles(false)
->downloadable()
->required()
->acceptedFileTypes(['text/csv']),
Radio::make('type')
->label('Type of Products')
->options([
'1' => 'Products',
'2' => 'Services',
])
->required(),
])
->statePath('data');
}
If I replace these components with say a Text input, it works as expected but the code above, attempts to submit even without data. Now if I copy and paste these into one of my resource forms, the validation works correctly. Not entirely sure what is going on and happy to provide more code etc.
18 Replies
Dennis Koch
Dennis Koch4mo ago
What does you submit() method look like?
Damien
Damien4mo ago
Sorry, was away doing a hotfix. Let me grab that for you. at the minute it looks like this:
public function save(): void
{
dd('saving...');
}
public function save(): void
{
dd('saving...');
}
however that is because I stripped it back, it was like this:
public function save(): void
{
$attachment = $this->data['attachment'];
$type = $this->data['type'];
$fileName = array_key_first($attachment);
$file = $attachment[$fileName];
$fileContents = file_get_contents($file->getRealPath());
$rows = array_map('str_getcsv', explode("\r\n", $fileContents));

switch ($type) {
case 'stock-products':
$this->handleStockProductImport($rows);
break;
// case 'bom-products':
// $this->handleBomProductImport($rows);
// break;
default:
break;
}
}
public function save(): void
{
$attachment = $this->data['attachment'];
$type = $this->data['type'];
$fileName = array_key_first($attachment);
$file = $attachment[$fileName];
$fileContents = file_get_contents($file->getRealPath());
$rows = array_map('str_getcsv', explode("\r\n", $fileContents));

switch ($type) {
case 'stock-products':
$this->handleStockProductImport($rows);
break;
// case 'bom-products':
// $this->handleBomProductImport($rows);
// break;
default:
break;
}
}
I really wish it didn't copy whitespace from jetbrains products!
Damien
Damien4mo ago
Yes indeed, here is my whole file to make life a little easier.
<?php

namespace App\Livewire;

use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Radio;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Livewire\Component;

class BulkProductImport extends Component implements HasForms
{
use InteractsWithForms;

public ?array $data = [];

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

public function form(Form $form): Form
{
return $form
->schema([
FileUpload::make('attachment')
->previewable(false)
->storeFiles(false)
->downloadable()
->required()
->acceptedFileTypes(['text/csv']),
Radio::make('type')
->label('Type of Products')
->options([
'1' => 'Products',
'2' => 'Services',
])
->required(),
])
->statePath('data');
}

public function save(): void
{
dd('saving...');
}

public function render(): View
{
return view('livewire.bulk-product-import');
}
}
<?php

namespace App\Livewire;

use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Radio;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Illuminate\Contracts\View\View;
use Livewire\Component;

class BulkProductImport extends Component implements HasForms
{
use InteractsWithForms;

public ?array $data = [];

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

public function form(Form $form): Form
{
return $form
->schema([
FileUpload::make('attachment')
->previewable(false)
->storeFiles(false)
->downloadable()
->required()
->acceptedFileTypes(['text/csv']),
Radio::make('type')
->label('Type of Products')
->options([
'1' => 'Products',
'2' => 'Services',
])
->required(),
])
->statePath('data');
}

public function save(): void
{
dd('saving...');
}

public function render(): View
{
return view('livewire.bulk-product-import');
}
}
LeandroFerreira
LeandroFerreira4mo ago
$data = $this->form->getState();
dd($data);
$data = $this->form->getState();
dd($data);
?
Damien
Damien4mo ago
Inside of the save method?
LeandroFerreira
LeandroFerreira4mo ago
yes
Damien
Damien4mo ago
huh, doing that makes the validation work, and if I remove the dd it also works so I guess I just need to change my method to access the form state first. This gives a slightly different way of handling it but I should be able to sort it from here I think. I will keep this open until I have however.
LeandroFerreira
LeandroFerreira4mo ago
getState() will validate the form You should follow this section https://discord.com/channels/883083792112300104/1205152125441671238/1205172334974214184
Damien
Damien4mo ago
Ah where I messed up was copying another, similar component where the validation was working without this step which lead me down the wrong path! Thank you Leandro! Marked your original reply as the solution and updated the tag.
MAF
MAF4mo ago
I have the same issue, but for some weird reason! calling $this->form->getState(); in the submit function returns an empty array, and $this->form; returns an empty form instance, however $this-data returns the data correctly;
LeandroFerreira
LeandroFerreira4mo ago
please share the whole code
MAF
MAF4mo ago
I moved the logic to boot() instead of mount() and everything worked perfectly!
Dennis Koch
Dennis Koch4mo ago
Why would you call $this->form->getState() during mount?
MAF
MAF4mo ago
Sorry, I think there is a misunderstanding here. I said, calling this->form->getState() in submit function.
Dennis Koch
Dennis Koch4mo ago
Okay, but what did you move to boot()? 🤔
MAF
MAF4mo ago
Pastebin
Pastebin.com is the number one paste tool since 2002. Pastebin is a website where you can store text online for a set period of time.
MAF
MAF4mo ago
@Dennis Koch never mind, I found a lot of mistakes in my code. Thank you