filamentphp / filament

A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS.
https://filamentphp.com
MIT License
19.18k stars 2.95k forks source link

Bug with reactive field and afterStateUpdate #7571

Closed lepresk closed 1 year ago

lepresk commented 1 year ago

Package

filament/filament

Package Version

v3.0.12

Laravel Version

v10.18.0

Livewire Version

No response

PHP Version

8.1.12

Problem description

I am currently facing an issue with a field marked as reactive to update another field accordingly. Specifically, I have two fields inside a Repeater, namely "quantity" and "total". My objective is that when the quantity changes, the "total" field should be automatically calculated accordingly. However, when I change the quantity to a value like 1111, the "quantity" field seems to reset with a truncated value, for example, 1.

https://github.com/filamentphp/filament/assets/10780686/90ce4754-facd-4720-9f0b-c02594764e9a

Expected behavior

When the user enters a value in the "quantity" field, this value should not be altered or truncated.

Steps to reproduce

Forms\Components\Repeater::make('billets')
    // ... (other Repeater parameters)
    ->schema([
        Forms\Components\Select::make('cash_denomination_id')
            // ... (other Select field parameters)
        ),

        Forms\Components\TextInput::make('quantity')
            // ... (other Quantity field parameters)
            ->reactive()
            ->afterStateUpdated(function($state, callable $get, callable $set) {
                $quantity = intval($state);
                $denomination = CashDenomination::find($get('cash_denomination_id'));
                $total = $denomination->value * $quantity;

                $set('total', $total);
            }),

        Forms\Components\TextInput::make('total')
            // ... (other Total field parameters)
    ])
  1. Clone the repository to your local environment: git clone https://github.com/lepresk/filament-reactive-bug.git
  2. Install all dependencies and Filament: Run composer install and php artisan filament:install --panels
  3. Seed the CashDenomination table: Execute php artisan db:seed CashDenominationSeeder
  4. Create a user to log in to the dashboard: Run php artisan make:filament-user
  5. Navigate to the "Deposits" section and click on "New."
  6. Enter a value in one of the "quantity" fields within the repeater to observe the bug.

Reproduction repository

https://github.com/lepresk/filament-reactive-bug.git

Relevant log output

No response

awcodes commented 1 year ago

I'm not sure this is a bug. It looks like a network latency issue. i.e. by setting it to reactive you are saying that it should change on every input, so you are typing faster than the network can process the request and send it back to you, so Livewire is updating the state based on what it was when you sent the request initially.

Try using ->live(debounce: 500ms) or similar or only calculate it on blur.

tanthammar commented 1 year ago

This can be closed. Downloaded and tested with your repository. Just add ->debounce(600), and the problem is gone. … or a debounce value of your preference :-)

Forms\Components\TextInput::make('quantity')
                                          ->label('Quanity')
                                          ->numeric()
                                          ->default(0)
                                          ->required()
                                          ->reactive()
                                          ->debounce(600)
                                          ->afterStateUpdated(function($state, callable $get, callable $set) {
                                              $quantity = intval($state);
                                              $denomination = CashDenomination::find($get('cash_denomination_id'));
                                              $total = $denomination->value * $quantity;

                                              $set('total', $total);
                                          }),
lepresk commented 1 year ago

I can confirm that adding debouce solve the issue! 👍

raiika commented 5 months ago

It's true that debounce solve the issue for typing only small number, but if you type a bunch of number until you trigger the 600ms, than you get the same result

example:

actual typing : 12345678901234567890
result        : 123456789012345678

I just bump into this issue when following this article https://laraveldaily.com/post/filament-repeater-live-calculations-on-update,
And also filament example has the same issue https://demo-crm.filamentexamples.com/admin/quotes/create

I don't have much knowledge about livewire or filament,
but I suggests to make debounce or new feature for a setTimeout with clearTimeout when typing, so after the user finish typing, it then should trigger the update (ajax or fetch or something that triggers the bug).

lepresk commented 5 months ago

Agree

zaidpirwani commented 4 months ago

I understand this specific issue is closed, Shall I create another issue ? similar issue I face as well in my forms the input value is truncated or goes missing

I have an image uploaad field as well and if I give it a file to upload and then enter other fields in the meantime, similar missing values/form field reset happens

I am trying to work with onblur and large debounce values, but I think this needs a better resolution

zaidpirwani commented 4 months ago

I just bump into this issue when following this article https://laraveldaily.com/post/filament-repeater-live-calculations-on-update, And also filament example has the same issue https://demo-crm.filamentexamples.com/admin/quotes/create

FilamentExampels and Laravel daily is run by another dev, not directly by filament people - I will check if similar issue is in the official filament demo and if not, how is it solved there.

tanthammar commented 4 months ago

In my humble personal opinion, this is not a bug. It is up to the dev to set longer debounce values based on the expected length of the input value. Also to consider the type of user. I always have to consider that the age of our users are 60+, they type sloooowly. I can never use the default 500.

To me, an issue is when something is not working. There is nothing wrong with how Filament handles debounce. It simply follows the value you provide it with.

Consider ->live(onBlur: true) instead of ->live(debounce: ...) if that is an option.

https://filamentphp.com/docs/3.x/forms/advanced#the-basics-of-reactivity https://filamentphp.com/docs/3.x/forms/advanced#reactive-fields-on-blur

zaidpirwani commented 4 months ago

THANKS - yes, live(onblur) works :)