Skip to content

Instantly share code, notes, and snippets.

@sjardim
Last active November 4, 2023 21:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sjardim/ad65961826c31c2af6210317ed541158 to your computer and use it in GitHub Desktop.
Save sjardim/ad65961826c31c2af6210317ed541158 to your computer and use it in GitHub Desktop.
Creating a Money custom field for Laravel Filament
<x-dynamic-component
:component="$getFieldWrapperView()"
:id="$getId()"
:label="$getLabel()"
:label-sr-only="$isLabelHidden()"
:helper-text="$getHelperText()"
:hint="$getHint()"
:hint-action="$getHintAction()"
:hint-color="$getHintColor()"
:hint-icon="$getHintIcon()"
:required="$isRequired()"
:state-path="$getStatePath()"
>
{{--https://alpinejs.dev/plugins/mask--}}
<div class="filament-forms-text-input-component flex items-center space-x-2 rtl:space-x-reverse group"
x-data="{ state: $wire.entangle('{{ $getStatePath() }}').defer }">
<span class="whitespace-nowrap group-focus-within:text-primary-500 text-gray-400">
@if ($label = $getPrefixLabel())
<span>{{ $label }}</span>
@endif
</span>
<div class="flex-1">
<input {!! $isDisabled() ? 'disabled' : null !!}
class="block w-full transition duration-75 border-gray-300 rounded-lg shadow-sm focus:border-primary-500 focus:ring-1 focus:ring-inset focus:ring-primary-500 disabled:opacity-70 dark:bg-gray-700 dark:text-white dark:focus:border-primary-500 dark:border-gray-600"
wire:model.defer="{{ $getStatePath() }}" placeholder="0,00" type="text"
x-mask:dynamic="$money($input, ',')" />
</div>
</div>
</x-dynamic-component>
<?php
declare(strict_types=1);
namespace App\Forms\Components;
use Filament\Forms\Components\Concerns\HasAffixes;
use Filament\Forms\Components\Field;
class Money extends Field
{
use HasAffixes;
protected string $view = 'forms.components.money';
}
@sjardim
Copy link
Author

sjardim commented Apr 19, 2023

On your Resource Edit page (e.g. EditContract):

protected function mutateFormDataBeforeFill(array $data): array
    {
        $data['monthly_fee_in_cents'] = number_format($data['monthly_fee_in_cents']/100, 2, ',', '.');
        return $data;
    }

    protected function mutateFormDataBeforeSave(array $data): array
    {
        $data['monthly_fee_in_cents'] = preg_replace('/[ ,|.]+/', '', $data['monthly_fee_in_cents']);

        return $data;
    }

On the Create page:

protected function mutateFormDataBeforeCreate(array $data): array
     {
         $data['monthly_fee_in_cents'] = preg_replace('/[ ,|.]+/', '', $data['monthly_fee_in_cents']);

         return $data;
     }

@sjardim
Copy link
Author

sjardim commented Apr 19, 2023

README

This trick is based on Brazilian Phone Number field by Leandro C. Ferreira

IMPORTANT: in this example, the value is stored as integer on the DB.

  1. Create new field
    php artisan make:form-field Money

  2. Add Alpinejs Mask plugin on the boot method of your AppServiceProvider class

Filament::registerScripts([
                'https://unpkg.com/@alpinejs/mask@3.x.x/dist/cdn.min.js',
            ], true);

Usage

Money::make('monthly_fee_in_cents')
                ->label('Fee')
                ->prefix('€')
                ->required(),

Preview:

CleanShot 2023-04-19 at 22 40 14

@dougkusanagi
Copy link

dougkusanagi commented Apr 22, 2023

Exatamente o que eu tava procurando! Não achei nenhuma forma de dividir o valor por 100 antes de enviar pro inputText, vou tentar implementar aqui e vlw @sjardim !

ps: acho que tem um ")" extra na linha 28 do arquivo "money.blade.php" fora isso a máscara parece ter funcionado como deveria. Será que tem uma mais parecida com a $.mask do falecido jQuery, que ao digitar 1 ele já preenche 0.01?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment