#afterStateUpdated $old does not work after using Builder/Block

3 messages · Page 1 of 1 (latest)

undone terrace
#

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);
                ])
        ]);
}

Any idea what could be wrong?

winged onyxBOT
#

To help others find answers, you can mark your question as solved via Right click solution message -> Apps -> ✅ Mark Solution

undone terrace
#

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

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

A full-stack framework for Laravel that takes the pain out of building dynamic UIs. - livewire/livewire

GitHub

A full-stack framework for Laravel that takes the pain out of building dynamic UIs. - livewire/livewire