F
Filament12mo ago
Damien

How to derive a value from another TextInput field correctly.

Firstly, if there is a specific piece of documentation for doing this, please point me there as I struggled to find it but otherwise, here is what I am trying to do. I have the following form (attached image) and in the highlight box you will see 2 prices, gbp and eur - What I want to be able to do is use a multiplier that is stored in the database to set the value of eur once i have entered a price for gbp - I still want to be able to change this manually so it does not have to be disabled or anything but it would be nice if it worked in reverse. I.e, changing euro, changes the price of gbp I have the following TextInput components:
TextInput::make('price_gbp')
->label('Price (GBP)')
->prefix('£')
->minValue(0)
->maxValue(999999)
->required()
->numeric(),
TextInput::make('price_eur')
->label('Price (EUR)')
->prefix('€')
->minValue(0)
->maxValue(999999)
->required()
->numeric(),
TextInput::make('price_gbp')
->label('Price (GBP)')
->prefix('£')
->minValue(0)
->maxValue(999999)
->required()
->numeric(),
TextInput::make('price_eur')
->label('Price (EUR)')
->prefix('€')
->minValue(0)
->maxValue(999999)
->required()
->numeric(),
I have looked at both the ->default() method and ->afterStateUpdated() method but failed to get either working in a way that I would like to (probably a me issue) any advice or guidance appreciated as always!
No description
9 Replies
ChesterS
ChesterS12mo ago
Have a look at this https://filamentphp.com/docs/3.x/forms/advanced#injecting-the-state-of-another-field that page has other advanced things you can do with forms to affect other fields
Damien
DamienOP12mo ago
ah thank you, I think i did come across that but I wasn't entirely sure on how to then set it or which method to use for the callback. trying to do something like the following
->formatStateUsing(function ($state, Get $get): string {
return $get('price_gbp') * 1.17;
}),
->formatStateUsing(function ($state, Get $get): string {
return $get('price_gbp') * 1.17;
}),
but this doesn't achieve what I am ideally looking to do. It doesn't really say in the docs which method the callback could / should be called from. this is the latest I have
TextInput::make('price_eur')
->label('Price (EUR)')
->prefix('€')
->minValue(0)
->maxValue(999999)
->step('0.01')
->type('number')
->formatStateUsing(function (Get $get) {
// Retrieve the value of the 'price_gbp' field
$priceGBP = $get('price_gbp');

// Perform conversion logic here to update the 'price_eur' field
$conversionRate = 1.2; // Replace with actual conversion rate

// Return the updated value for the 'price_eur' field
return $priceGBP * $conversionRate;
}),
TextInput::make('price_eur')
->label('Price (EUR)')
->prefix('€')
->minValue(0)
->maxValue(999999)
->step('0.01')
->type('number')
->formatStateUsing(function (Get $get) {
// Retrieve the value of the 'price_gbp' field
$priceGBP = $get('price_gbp');

// Perform conversion logic here to update the 'price_eur' field
$conversionRate = 1.2; // Replace with actual conversion rate

// Return the updated value for the 'price_eur' field
return $priceGBP * $conversionRate;
}),
However, price_eur is always 0 so I need this value to update once price_gbp has changed. afterStateUpdates does not seem to work for whatever reason.
ChesterS
ChesterS12mo ago
using ->afterStateUpdated to update the other field
Damien
DamienOP12mo ago
This is what I have been trying but for some reason it doesn't update. I don't know if the modal breaks it somehow. If I use dd it doesn't trigger until I click outside of the modal, I will grab a video.
Damien
DamienOP12mo ago
Damien
DamienOP12mo ago
see the delay?
ChesterS
ChesterS12mo ago
you need to set ->live() (or something similar) Also check debounce delays etc
Damien
DamienOP12mo ago
okay thank you I will take a look after some food Got it working thank you Chester. This was the final code that did the trick:
TextInput::make('price_gbp')
->label('Price (GBP)')
->prefix('£')
->minValue(0)
->maxValue(999999)
->type('number')
->step('0.01')
->afterStateUpdated(fn (Set $set, ?string $state) => $set('price_eur', $state * 1.2))
->live(debounce: 500),
TextInput::make('price_gbp')
->label('Price (GBP)')
->prefix('£')
->minValue(0)
->maxValue(999999)
->type('number')
->step('0.01')
->afterStateUpdated(fn (Set $set, ?string $state) => $set('price_eur', $state * 1.2))
->live(debounce: 500),
Want results from more Discord servers?
Add your server