ariaieboy / filament-currency

Enhanced Currency Related stuff for Filament
MIT License
42 stars 8 forks source link

[Bug]: #25

Closed nielsvh2103 closed 4 months ago

nielsvh2103 commented 4 months ago

What happened?

Hey there, when using the text input (currencyMask)

Like this:

                             TextInput::make('price')
                                    ->nullable()
                                    ->currencyMask(thousandSeparator: '.', decimalSeparator: ',')

The issue we experience even with live() on reload is that it doesnt properly apply the format. Example: 1000.33 in the database should show 1.000,33 on the ui, this doesnt happen until you focus on the input.

How to reproduce the bug

Set currencyMask on a from text input and try using euro's We use:

                             TextInput::make('price')
                                    ->nullable()
                                    ->currencyMask(thousandSeparator: '.', decimalSeparator: ',')

MONEY_DEFAULTS_CURRENCY=EUR

Then on reload, you will notice it won't be 1.000.33 (example number) But it will actually show 1000.33, when i focus on the input it properly applies.

This is due to your code, i can show this right here:

in your view currency-mask i have changed the following:

    {
        input:\$wire.{$applyStateBindingModifiers("\$entangle('{$statePath}')")},
        masked:'',
        init() {
            \$nextTick(() => {
                this.updateMasked();
            });
            \$watch('masked', () => this.updateInput());
            \$watch('input', () => this.updateMasked());
        },
        updateMasked(){
            if(typeof Number(this.input) === 'number'){
                \$el.value = this.input?.toString().replaceAll('.','$decimalSeparator');
                this.masked = \$el.value;
                \$el.dispatchEvent(new Event('input'));
            }
        },
        updateInput(){
            this.input = \$el.value?.replaceAll('$thousandSeparator','').replaceAll('$decimalSeparator','.');
        }
    }

What i changed: The next tick i changed to updateMasked() and in there after properly updating the mask you set the value. This way, on reload it will work aswell.

Instead of:

        init(){
        \$nextTick(()=>this.masked = this.input?.toString().replaceAll('.','$decimalSeparator'));
        \$watch('masked',()=>this.updateInput());
        \$watch('input',()=>this.updateMasked());
        },
        updateMasked(){
            if(typeof Number(this.input) === 'number'){
                \$el.value = this.input?.toString().replaceAll('.','$decimalSeparator');
                \$el.dispatchEvent(new Event('input'));
            }
        },

Because in the updateMasked method you also dispatch an input event, which fixes the issue on reload.

With the original code: Screenshot 2024-05-27 at 16 57 07 This is shown on reload. On focus it fixes itself due to firing updateMasked.

With the updated snippet; Screenshot 2024-05-27 at 16 57 58

Due to firing a new input event, it will properly initialize the thousand separator on load as well, due to calling updateMasked and that one will call updateInput after.

Package Version

1.7.0

PHP Version

8.3.6

Laravel Version

11.8.0

Which operating systems does with happen with?

macOS

Notes

No response

ariaieboy commented 4 months ago

thanks for your report Can you make a PR using the codes that you provided?

nielsvh2103 commented 4 months ago

@ariaieboy will do in a bit!

nielsvh2103 commented 4 months ago

I made the pull request you can check it out above ^^ @ariaieboy

ariaieboy commented 4 months ago

I made the pull request you can check it out above ^^ @ariaieboy

I am working on it

ariaieboy commented 4 months ago

test version https://github.com/ariaieboy/filament-currency/releases/tag/1.7.1