pelmered / filament-money-field

Money field powered by Money PHP
MIT License
40 stars 19 forks source link

Support for dynamically updating currency and locale of MoneyInput #42

Open AlexanderBV opened 4 weeks ago

AlexanderBV commented 4 weeks ago

Describe the bug I'm encountering an error when trying to dynamically set the currency and locale for the MoneyInput component in Filament forms. The error occurs specifically when trying to use a closure for the currency property.

Error Message Typed property Filament\Forms\Components\Component::$container must not be accessed before initialization

The error is triggered by this line:

->currency(fn ($get) => $get('unit_price_currency'))

Steps To Reproduce:

```php
use Filament\Forms\Components\Grid;
use Filament\Forms\Components\Hidden;
use Filament\Forms\Components\Select;
use Pelmered\FilamentMoneyField\Forms\Components\MoneyInput;
use Filament\Forms\Form;
use Filament\Forms\Get;
use Filament\Forms\Set;
use App\Models\Catalog;
use App\Enums\RateType;

public function form(Form $form): Form
{
    return $form
        ->schema([
            Select::make('currency_id')
                ->label('Moneda')
                ->relationship('currency', 'name')
                ->searchable(['code', 'name'])
                ->preload()
                ->reactive()
                ->required()
                ->afterStateUpdated(function (Set $set, Get $get) {
                    $currency = Catalog::find($get('currency_id'));
                    $set('unit_price_currency', $currency->code);
                    $set('unit_price_locale', $currency->properties['locale'] ?? 'es_PE');
                })
                ->afterStateHydrated(function (Set $set, Get $get, $state) {
                    $currency = Catalog::find($state);
                    $set('unit_price_currency', $currency->code);
                    $set('unit_price_locale', $currency->properties['locale'] ?? 'es_PE');
                }),
            Hidden::make('unit_price_currency'),
            Hidden::make('unit_price_locale'),
            MoneyInput::make('unit_price')
                ->label('Precio')
                ->currency(fn ($get) => $get('unit_price_currency'))
                ->locale(fn ($get) => $get('unit_price_locale'))
        ]);
}

Changes have in global config:

// .env file settings MONEY_DEFAULT_LOCALE=es_PE MONEY_DEFAULT_CURRENCY=PEN

// Configuration published with php artisan vendor:publish --provider="Pelmered\FilamentMoneyField\FilamentMoneyFieldServiceProvider" --tag="config"

Expected behavior and actual behavior I expected the MoneyInput component to correctly use the dynamically set currency and locale values without causing initialization errors. Instead, it throws an error indicating that the property $container must not be accessed before initialization.

Screenshots Screenshot from 2024-06-26 11-31-49

Additional context I believe the issue might be related to the initialization of the $container property, which seems to be accessed before it is fully initialized. Any insights or solutions to this problem would be greatly appreciated. Thank you for your assistance!

Version of: This package: Latest Filament: 3.2 PHP: 8.2 Laravel: 10.10

pelmered commented 1 day ago

Thank you for the report! I will investigate this today.

pelmered commented 1 day ago

I don't believe this error has anything to with this plugin. It is how Filament works.

I think you have to do something like this:

                MoneyInput::make('price')
                          ->label('Precio')
                          ->afterStateUpdated(function (MoneyInput $component, bool $state) {
                              $component->currency(fn($get) => $get('unit_price_currency') ?? 'USD')
                                        ->locale(fn($get) => $get('unit_price_locale') ?? 'es_PE');
                          })
pelmered commented 1 day ago

I have now tested some, and I'm not sure how well it works to change the field dynamically like this. This is something I will have to look into in the future. For now I would probably just use a currency select and a normal input without localized format. For displaying it should work with the MoneyColumn and the MoneyEntry.

If you find a way to support this, please let me know.