leandrocfe / filament-ptbr-form-fields

This package provides custom form fields for Filament (>=v2.17.28) that are commonly used in Brazilian web applications, such as CPF/CNPJ validation, phone number formatting, money with currency symbol, and CEP integration with ViaCep.
MIT License
97 stars 17 forks source link

[Bug]: Salvando campo money com 0,00 mesmo quando nada é preenchido. #15

Open marcosrnuness opened 12 months ago

marcosrnuness commented 12 months ago

What happened?

Quando salva o registro os campos money salvam adicionando sempre 0,00 quando nada é preenchido e nem é dado foco no input, isto acontece mesmo estando o initialValue setado como null.

How to reproduce the bug

Crie um campo money, adicione o initialValue como null, adicione ou edite um registro em que os valores não estejam preenchidos e salve. Ao salvar o campo é preenchido com 0,00, não respeitando que o valor não esteja preenchido onde deveria salvar como null. No meu caso estou usando um campo decimal(18,2).

Outro detalhe é que quando dá o foco no campo através da tabulação ele preenche automaticamente com 0,00 mesmo não digitando nada, isto não acontece clicando com o mouse no input.

Package Version

3.0.1

PHP Version

8.2.2

Laravel Version

10.27.0

Which operating systems does with happen with?

Windows

Notes

No response

rodrigomedeirosbrazil commented 11 months ago

Estou com esse problema. Percebi que o AlpineJS muda o valor do x-model antes de rodar o x-on:keyup

https://github.com/alpinejs/alpine/discussions/2862

to procurando um jeitinho disso funcionar direito, qualquer coisa coloco aqui.

Eu uso campo de currency em decimal, por isso eu faço a conversão.

rodrigomedeirosbrazil commented 11 months ago

Não consegui dar um jeito no javascript, resolvi ir pro POG, e deixar só os números, e adicionar o ponto decimal.

public function dehydrateMask(bool|Closure $condition = true): static
    {
        if ($condition) {
            $this->dehydrateStateUsing(
                fn ($state): ?float => $state ?
                    floatval(
                        Str::of($state)
                            ->replace('.', '')
                            ->replace(',', '')
                            ->substrReplace('.', -2, 0)
                            ->toString()
                    ) :
                    null
            );
        } else {
            $this->dehydrateStateUsing(null);
        }

        return $this;
    }
rodrigomedeirosbrazil commented 11 months ago

Consegui uma coisa melhor hein Despachar o evento de input depois do JS trocar o valor só coloquei a linha $el.dispatchEvent(new Event(\'input\'));

->extraAlpineAttributes([

                'x-on:keypress' => 'function() {
                        var charCode = event.keyCode || event.which;
                        if (charCode < 48 || charCode > 57) {
                            event.preventDefault();
                            return false;
                        }
                        return true;
                    }',

                'x-on:keyup' => 'function() {
                        var money = $el.value.replace(/\D/g, "");
                        money = (money / 100).toFixed(2) + "";
                        money = money.replace(".", ",");
                        money = money.replace(/(\d)(\d{3})(\d{3}),/g, "$1.$2.$3,");
                        money = money.replace(/(\d)(\d{3}),/g, "$1.$2,");

                        $el.value = money;
                        $el.dispatchEvent(new Event(\'input\'));
                    }',
            ])
rodrigomedeirosbrazil commented 11 months ago

@leandrocfe, ta de olho aqui na issue?

leandrocfe commented 11 months ago

Vou dar uma olhada assim que possível 👍

DanielLiberato commented 8 months ago

@rodrigomedeirosbrazil adicionando esse código $el.dispatchEvent(new Event(\'input\')); resolveu para min. geralmente se eu escrever 0,01 , ele mandava 0,001 e isso é um grande problema, mas adicionando o dispatch do evento que você falou dá certo, agora ele manda 0,01.

Outro ponto que eu peguei de bug aqui é que quando ele salva sem que haja alteração no input ele multiplicava por 10 então eu só removi a multiplicação do dehydrateStateUsing

->dehydrateStateUsing(
                fn ($state): ?float => $state ?
                    floatval(
                        Str::of($state)
                            ->replace('.', '')
                            ->replace(',', '.')
                            ->toString()
                    ):
                    null
            )

O código todo que resolveu aqui para min ficou assim.

 protected function setUp(): void
    {
        $this
            ->prefix('R$')
            ->maxLength(13)
            ->extraAlpineAttributes([

                'x-on:keypress' => 'function() {
                        var charCode = event.keyCode || event.which;
                        if (charCode < 48 || charCode > 57) {
                            event.preventDefault();
                            return false;
                        }
                        return true;                            
                    }',

                'x-on:keyup' => 'function() {
                        var money = $el.value.replace(/\D/g, "");
                        money = (money / 100).toFixed(2) + "";
                        money = money.replace(".", ",");
                        money = money.replace(/(\d)(\d{3})(\d{3}),/g, "$1.$2.$3,");
                        money = money.replace(/(\d)(\d{3}),/g, "$1.$2,");

                        $el.value = money;
                        $el.dispatchEvent(new Event(\'input\'));
                    }',
            ])
            ->dehydrateMask()
            ->default(0.00)
            ->formatStateUsing(fn ($state) => $state ? number_format(floatval($state), 2, ',', '.') : $this->initialValue);
    }

    public function dehydrateMask(bool|Closure $condition = true): static
    {

        if ($condition) {
            $this->dehydrateStateUsing(
                fn ($state): ?float => $state ?
                    floatval(
                        Str::of($state)
                            ->replace('.', '')
                            ->replace(',', '.')
                            ->toString()
                    ) :
                    null
            );
        } else {
            $this->dehydrateStateUsing(null);
        }

        return $this;
    }

    public function initialValue(null|string|int|float|Closure $value = '0,00'): static
    {
        $this->initialValue = $value;

        return $this;
    }

@leandrocfe

leandrocfe commented 1 month ago

@rodrigomedeirosbrazil @marcosrnuness @DanielLiberato

Verifiquem essa versão por favor https://github.com/leandrocfe/filament-ptbr-form-fields/releases/tag/3.1.0