F
Filament15mo ago
Bagus A

Accessing Form State

I am having difficulty to understand how to access form data in Form Builder. Let say I have this form and I want to generate part code and part description automatically based on other form fields. What I'm thinking right now is adding afterStateUpdate to every fields and trigger a method to generate the part code. But, inside afterStateUpdate I only have access to it's own field state not the entire state. If I try to use $this->form->getState() it doesn't work, (is it because it's a static function?).
->afterStateUpdated(function (Set $set, $state) {
$set('part_code', OrderResource::generatePartCode($state));
}),
->afterStateUpdated(function (Set $set, $state) {
$set('part_code', OrderResource::generatePartCode($state));
}),
No description
20 Replies
Rahaf
Rahaf15mo ago
If you want to take data from the database just add them in the form .
Bagus A
Bagus AOP15mo ago
Part code and part description is not stored in the database. I want to get current data in the form before saving to db.
Rahaf
Rahaf15mo ago
umm i am not sure , but you can use beforeCreate() in the create page
Bagus A
Bagus AOP15mo ago
beforeCreate() method will be called before the data in the form is saved to the database. I need to generate part code dynamically when user change other fields before uesr click create button. @rahafss It's just for preview only @rahafss
S. Mert ÖZTÜRK
S. Mert ÖZTÜRK15mo ago
Okay, i will try to help you, i understood you Firstly decide to when trigger new input shot For example; TextInput::make('title') ->live() ->afterStateUpdated(function (Get $get, Set $set, ?string $old, ?string $state) { if (($get('slug') ?? '') !== Str::slug($old)) { return; }
$set('slug', Str::slug($state)); }) But i think you want when all input is filled, right? If it is what you want, simple you can do this; //not important which input select one, TextInput::make('title') ->live() ->afterStateUpdated(function (Get $get, Set $set, ?string $old, ?string $state) { if ($get('input1') == "" or $get('input2') == "" or $get('input2') != "") { return; } $set('slug', Str::slug($state)); }) By this way, you can control all input and if anyone was empty, not set new input
Bagus A
Bagus AOP15mo ago
Thank you @S. Mert ÖZTÜRK, I don't know that I could add Get inside afterStateUpdate. The main idea is the same, adding afterStateUpdated to all fields.
toeknee
toeknee15mo ago
Did that resolve your issue
Bagus A
Bagus AOP15mo ago
Is there a solution where we can have like a global listener whenever a field is change without adding
->live()
->afterStateUpdated()
->live()
->afterStateUpdated()
to every fields?
toeknee
toeknee15mo ago
You can put the logic outside of it and just include the logic? The live is what adds the global listener
Bagus A
Bagus AOP15mo ago
Currently I"m using it like this:
->live()
->afterStateUpdated(function (Set $set, Get $get, $state) {
$set('part_code', OrderResource::generatePartCode($get));
$set('part_description', OrderResource::generateProductDescription($get));
}),
->live()
->afterStateUpdated(function (Set $set, Get $get, $state) {
$set('part_code', OrderResource::generatePartCode($get));
$set('part_description', OrderResource::generateProductDescription($get));
}),
Is it what you mean by put the logic outside?
toeknee
toeknee15mo ago
No, you are saying basically you have to duplicate the code in afterStateUpdated right for every field?
Bagus A
Bagus AOP15mo ago
yes Can you elaborate on putting the logic outside?
toeknee
toeknee15mo ago
So just build a function:
public static function partSetter(Set $set, Get $get, $state) {
$set('part_code', OrderResource::generatePartCode($get));
$set('part_description', OrderResource::generateProductDescription($get));
}
public static function partSetter(Set $set, Get $get, $state) {
$set('part_code', OrderResource::generatePartCode($get));
$set('part_description', OrderResource::generateProductDescription($get));
}
and just use: self::partSetter(Set $set, Get $get, $state)
Bagus A
Bagus AOP15mo ago
Where do I put self::partSetter(Set $set, Get $get, $state)?
toeknee
toeknee15mo ago
->afterStateUpdated(fn (Set $set, Get $get, $state) => self::partSetter($set, $get, $state))
->afterStateUpdated(fn (Set $set, Get $get, $state) => self::partSetter($set, $get, $state))
Bagus A
Bagus AOP15mo ago
I still have to add it to every fields shouldn't I?
toeknee
toeknee15mo ago
If course
Bagus A
Bagus AOP15mo ago
It's what I did, just different code.
toeknee
toeknee15mo ago
It' standardises the code into a single function, what you did means any change needing to be made has to be made to every field opposed to 1 function.
S. Mert ÖZTÜRK
S. Mert ÖZTÜRK15mo ago
You need spesific livewire component i think, in livewire component you can check real time function

Did you find this page helpful?