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:
<?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()
));
}
}
and in the form:
MoneyInput::make('price')->required(),
MoneyInput::make('price')->required(),
Now it is working but I wanted to know if there is scope for improvement.
1 Reply
Raziul Islam
Raziul Islam4mo ago
Preview:
No description