Is there a way to avoid duplicate afterStateUpdated methods ?

I have code like:
TextInput::make('number 1')
->live()
->afterStateUpdated(function (Get $get, Set $set): void {
$set('total', $get('number 1') + $get('number 2'));
})
->numeric(),
TextInput::make('number 2')
->live()
->afterStateUpdated(function (Get $get, Set $set): void {
$set('total', $get('number 1') + $get('number 2'));
})
->numeric(),
TextInput::make('total')
->numeric(),
TextInput::make('number 1')
->live()
->afterStateUpdated(function (Get $get, Set $set): void {
$set('total', $get('number 1') + $get('number 2'));
})
->numeric(),
TextInput::make('number 2')
->live()
->afterStateUpdated(function (Get $get, Set $set): void {
$set('total', $get('number 1') + $get('number 2'));
})
->numeric(),
TextInput::make('total')
->numeric(),
Simplified example; but basically, one field depends on two others. You have to have the same duplicated afterStateUpdated callback on both fields. It'd be a load nicer not to duplicate this and just have it attached to the total field. Is there a way to do this at all ? I've had a good dig but can't find anything. (I realise I can extract the method to a closure/other method; but it'd still be nice not to attach it twice)
Solution:
and..... simplest of all.... ``` \Filament\Forms\Components\Section::make() ->columns([...
Jump to solution
4 Replies
Dennis Koch
Dennis Koch2d ago
Extracting is probably the only option.
benlumley
benlumleyOP2d ago
this works... first, override on the page/livewire component:
public function updatedInteractsWithForms(string $statePath): void
{
parent::updatedInteractsWithForms($statePath);
$this->dispatchFormEvent('my-special-event');
}
public function updatedInteractsWithForms(string $statePath): void
{
parent::updatedInteractsWithForms($statePath);
$this->dispatchFormEvent('my-special-event');
}
then a field can listen for that event
TextInput::make('number 1')
->live()
->numeric(),
TextInput::make('number 2')
->live()
->numeric(),
TextInput::make('total')
->numeric()
->registerListeners([
'my-special-event' => [function (Component $component): void {

$set = new Set($component);
$get = new Get($component);

$set('total', $get('number 1') + $get('number 2'));
}],
]),
TextInput::make('number 1')
->live()
->numeric(),
TextInput::make('number 2')
->live()
->numeric(),
TextInput::make('total')
->numeric()
->registerListeners([
'my-special-event' => [function (Component $component): void {

$set = new Set($component);
$get = new Get($component);

$set('total', $get('number 1') + $get('number 2'));
}],
]),
kind of dirty/hacky i think for my situation, it may be worth taking the hackiness here; my afterStateUpdateds are quite intertwined.... it's not just field 3 depends on field 1 and field 2 more field a depends on field 1,2,3 field b depends on 1 + 4 field c depends on 2 so extracting out a closure is still messy defining the callbacks on the target field rather than the source field is a whole load cleaner/nicer to work with
Solution
benlumley
benlumley2d ago
and..... simplest of all....
\Filament\Forms\Components\Section::make()
->columns([
'default' => 1,
'sm' => 2,
'lg' => 3,
])
->schema([

TextInput::make('number 1')
->live()
->numeric(),
TextInput::make('number 2')
->live()
->numeric(),
TextInput::make('total')
->numeric()
])->afterStateUpdated(function (Get $get, Set $set): void {
$set('total', (int)$get('number 1') + (int)$get('number 2'));
}),
\Filament\Forms\Components\Section::make()
->columns([
'default' => 1,
'sm' => 2,
'lg' => 3,
])
->schema([

TextInput::make('number 1')
->live()
->numeric(),
TextInput::make('number 2')
->live()
->numeric(),
TextInput::make('total')
->numeric()
])->afterStateUpdated(function (Get $get, Set $set): void {
$set('total', (int)$get('number 1') + (int)$get('number 2'));
}),
benlumley
benlumleyOP2d ago
the callback will be 'busy' ; but i can separate that out main thing is it's defined once; so it should be less brittle / easier to keep in good shape

Did you find this page helpful?