Custom MoneyInput form field
I am using 'akaunting/laravel-money' package and custom cast that helps to store the value in cents in database and return money object while reading. ( A common approach for money)
The only issue was with filament TextInput which doesn't understands the object so I had to make a custom field.
This is the code:
and in the form:
Now it is working but I wanted to know if there is scope for improvement.
<?php
namespace App\Forms\Components;
use Filament\Forms\Components\TextInput;
use Filament\Support\RawJs;
class MoneyInput extends TextInput
{
use Concerns\HasMoneyAttributes;
protected function setUp(): void
{
parent::setUp();
$this->inputMode('decimal')
->minValue(0)
->prefix(fn (MoneyInput $component) => $component->getCurrency()->getPrefix())
->suffix(fn (MoneyInput $component) => $component->getCurrency()->getSuffix())
->stripCharacters(fn (MoneyInput $component) => $component->getCurrency()->getDecimalMark())
->formatStateUsing(function (MoneyInput $component, $state) {
if (is_array($state) && array_key_exists('amount', $state)) {
return money($state['amount'], key($state['currency']))->valueWithoutZeroes();
}
return $state;
})
->dehydrateStateUsing(function (MoneyInput $component, $state) {
return str_replace($component->getCurrency()->getThousandsSeparator(), '', $state);
});
}
public function getMask(): string|RawJs|null
{
if (! $this->evaluate($this->moneyMask)) {
return null;
}
return RawJs::make(sprintf(
"\$money(\$input, '%s', '%s', %d);",
$this->getCurrency()->getDecimalMark(),
$this->getCurrency()->getThousandsSeparator(),
$this->getCurrency()->getPrecision()
));
}
}
<?php
namespace App\Forms\Components;
use Filament\Forms\Components\TextInput;
use Filament\Support\RawJs;
class MoneyInput extends TextInput
{
use Concerns\HasMoneyAttributes;
protected function setUp(): void
{
parent::setUp();
$this->inputMode('decimal')
->minValue(0)
->prefix(fn (MoneyInput $component) => $component->getCurrency()->getPrefix())
->suffix(fn (MoneyInput $component) => $component->getCurrency()->getSuffix())
->stripCharacters(fn (MoneyInput $component) => $component->getCurrency()->getDecimalMark())
->formatStateUsing(function (MoneyInput $component, $state) {
if (is_array($state) && array_key_exists('amount', $state)) {
return money($state['amount'], key($state['currency']))->valueWithoutZeroes();
}
return $state;
})
->dehydrateStateUsing(function (MoneyInput $component, $state) {
return str_replace($component->getCurrency()->getThousandsSeparator(), '', $state);
});
}
public function getMask(): string|RawJs|null
{
if (! $this->evaluate($this->moneyMask)) {
return null;
}
return RawJs::make(sprintf(
"\$money(\$input, '%s', '%s', %d);",
$this->getCurrency()->getDecimalMark(),
$this->getCurrency()->getThousandsSeparator(),
$this->getCurrency()->getPrecision()
));
}
}
MoneyInput::make('price')->required(),
MoneyInput::make('price')->required(),
1 Reply
Preview: