afterStateUpdated $old does not work after using Builder/Block

Hey, i am currently trying to use afterStateUpdatedon a TextInput in combination with a Builder. The resource i am working on does have a *title *and a *slug *attribute that i have implemented as described in the documentation as well as a Builder. My issue is that after i have used any field inside a Block, the the $old parameter of the afterStateUpdated callback does equal the new value and not the old value. However, if i use any other field outside of the Builder, like test, before i change the title, it does work again. I am using the following code:
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('test'),
Forms\Components\TextInput::make('title')
->required()
->maxLength(255)
->live(onBlur: true)
->afterStateUpdated(function (Forms\Get $get, Forms\Set $set, ?string $old, ?string $state) {
if (($get('slug') ?? '') !== Str::slug($old)) {
return;
}

$set('slug', Str::slug($state));
}),
Forms\Components\TextInput::make('slug')
->required()
->maxLength(255),

Forms\Components\Builder::make('data')
->blocks([
Builder\Block::make('heading')
->schema([
Components\TextInput::make('content')
->label('Heading')
->required(),
Components\Select::make('level')
->options([
'h1' => 'Heading 1',
'h2' => 'Heading 2',
'h3' => 'Heading 3',
'h4' => 'Heading 4',
'h5' => 'Heading 5',
'h6' => 'Heading 6',
])
->required()
])
->columns(2);
])
]);
}
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('test'),
Forms\Components\TextInput::make('title')
->required()
->maxLength(255)
->live(onBlur: true)
->afterStateUpdated(function (Forms\Get $get, Forms\Set $set, ?string $old, ?string $state) {
if (($get('slug') ?? '') !== Str::slug($old)) {
return;
}

$set('slug', Str::slug($state));
}),
Forms\Components\TextInput::make('slug')
->required()
->maxLength(255),

Forms\Components\Builder::make('data')
->blocks([
Builder\Block::make('heading')
->schema([
Components\TextInput::make('content')
->label('Heading')
->required(),
Components\Select::make('level')
->options([
'h1' => 'Heading 1',
'h2' => 'Heading 2',
'h3' => 'Heading 3',
'h4' => 'Heading 4',
'h5' => 'Heading 5',
'h6' => 'Heading 6',
])
->required()
])
->columns(2);
])
]);
}
Any idea what could be wrong?
2 Replies
Patrick | Der Echte!
This seems to be casued by multiple properties being updated by one Livewire request. Livewire will iterate each property to be updated and trigger the *update * event for said property. https://github.com/livewire/livewire/blob/main/src/Mechanisms/HandleComponents/HandleComponents.php#L290 Doing so, Livewire will call all updating Hooks on the Component. https://github.com/livewire/livewire/blob/main/src/Features/SupportLifecycleHooks/SupportLifecycleHooks.php#L68 This will call Filament's updatingInteractsWithForms, which will write the current $data to $oldFormState['data']. https://github.com/filamentphp/filament/blob/3.x/packages/forms/src/Concerns/InteractsWithForms.php#L63C20-L63C46 All of this is done before any updated hook is executed, so it will result in $oldFormState['data'] equalling to the new data minus the last updated property. This does result in my $old value being wrong. I am not quite sure if this is the right way to keep track of old data, as Livewire does not seem to update the properties in order anyways. In case of an updating event context, should the $oldFormState['data'] not only be set once and not for every update trigger?
GitHub
filament/packages/forms/src/Concerns/InteractsWithForms.php at 3.x ...
A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS. - filamentphp/filament
GitHub
livewire/src/Features/SupportLifecycleHooks/SupportLifecycleHooks.p...
A full-stack framework for Laravel that takes the pain out of building dynamic UIs. - livewire/livewire
GitHub
livewire/src/Mechanisms/HandleComponents/HandleComponents.php at ma...
A full-stack framework for Laravel that takes the pain out of building dynamic UIs. - livewire/livewire
rabol
rabol3mo ago
did you ever find a solution for this ?
Want results from more Discord servers?
Add your server