Reputation: 867
I'm having an issue with Filament 3 where a numeric TextInput field is automatically truncating numbers. For example, when I enter "1000", it immediately becomes "10". Here's my current code in a Resource form:
<?php
namespace App\Filament\Resources;
use App\Enum\PurchaseOrderStatus;
use App\Filament\Resources\PurchaseOrderResource\Pages;
use App\Models\PurchaseOrder;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Actions\ActionGroup;
use Filament\Tables\Table;
class PurchaseOrderResource extends Resource
{
protected static ?string $model = PurchaseOrder::class;
protected static ?string $navigationIcon = 'heroicon-o-shopping-cart';
protected static ?string $navigationGroup = 'Manufacturing Management';
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Wizard::make([
// Step 1: General PO Information
Forms\Components\Wizard\Step::make('PO Details')
->schema([
Forms\Components\Select::make('supplier_id')
->relationship('supplier', 'name')
->required()
->label('Supplier'),
Forms\Components\TextInput::make('po_number')
->required()
->reactive()
->default(fn() => self::generateUniquePONumber()) // Auto-generate unique PO number
->maxLength(50)
->label('PO Number')
->readonly(), // Prevent manual editing,
Forms\Components\DatePicker::make('po_date')
->required()
->label('PO Date'),
Forms\Components\DatePicker::make('expected_delivery_date')
->label('Expected Delivery Date'),
Forms\Components\Select::make('status')
->options(PurchaseOrderStatus::class)
->enum(PurchaseOrderStatus::class)
->required()
->label('Status'),
Forms\Components\TextInput::make('total_amount')
->numeric()
->label('Total Amount')
->visible(fn($record) => $record !== null)
->prefix('£E') // Add the prefix here
->disabled(),
Forms\Components\Textarea::make('notes')
->columnSpanFull()
->label('Notes'),
])->columns(2),
// Step 2: Material Entries
Forms\Components\Wizard\Step::make('Material Details')
->schema([
Forms\Components\Repeater::make('purchaseOrderItems') // Changed from po_details to purchaseOrderItems
->relationship()
->label('Materials')
->schema([
Forms\Components\Select::make('material_id')
->options(function () {
return \App\Models\Material::pluck('material_name', 'id');
})
->required()
->label('Material')
->searchable(),
Forms\Components\TextInput::make('quantity_in_kilos')
->numeric()
->required()
->label('Quantity (kilos)')
->reactive(),
Forms\Components\TextInput::make('quantity_in_grams')
->required()
->numeric()
->default(0)
->reactive()
->readOnly(),
Forms\Components\TextInput::make('unit_price')
->numeric()
->required()
->label('Unit Price')
->reactive(),
Forms\Components\TextInput::make('subtotal')
->disabled()
->label('Subtotal')
->dehydrated(false)
->reactive()
->prefix('£E')
->formatStateUsing(fn($state) => number_format($state ?? 0, 2)),
])
->minItems(1)
->columns(5)
->columnSpanFull()
->reactive(),
]),
])->columnSpanFull()
->submitAction('Save PO')
]);
}
private static function generateUniquePONumber(): string
{
do {
$poNumber = 'OPO-' . mt_rand(100000, 999999);
} while (PurchaseOrder::where('po_number', $poNumber)->exists());
return $poNumber;
}
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('supplier.name')
->numeric()
->sortable(),
Tables\Columns\TextColumn::make('po_number')
->searchable(),
Tables\Columns\TextColumn::make('po_date')
->date()
->sortable(),
Tables\Columns\TextColumn::make('expected_delivery_date')
->date()
->label('Delivery Date')
->sortable(),
Tables\Columns\TextColumn::make('status'),
Tables\Columns\TextColumn::make('total_amount')
->numeric()
->formatStateUsing(fn($state) => '£E' . number_format($state, 2)) // Add the prefix and format the number
->sortable(),
Tables\Columns\TextColumn::make('created_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
Tables\Columns\TextColumn::make('updated_at')
->dateTime()
->sortable()
->toggleable(isToggledHiddenByDefault: true),
])
->filters([
//
])
->actions([
ActionGroup::make(
[
Tables\Actions\EditAction::make(),
Tables\Actions\ViewAction::make(),
Tables\Actions\DeleteAction::make(),
]
)
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
]);
}
public static function getRelations(): array
{
return [
//
];
}
public static function getPages(): array
{
return [
'index' => Pages\ListPurchaseOrders::route('/'),
'create' => Pages\CreatePurchaseOrder::route('/create'),
'edit' => Pages\EditPurchaseOrder::route('/{record}/edit'),
];
}
}
This is work fine and problem start appear after i tried to set state to change quntit in grams based on quantity in kilos Here's my current code cause the problem:
Forms\Components\TextInput::make('quantity_in_kilos')
->numeric()
->required()
->label('Quantity (kilos)')
->reactive()
->afterStateUpdated(function (Get $get, Set $set, $state) {
// Convert kilos to grams (1 kilo = 1000 grams)
$grams = $state * 1000;
$set('quantity_in_grams', $grams);
})
Adding numeric constraints:
->minValue(0)
->maxValue(999999.99)
Using input mode and step:
->inputMode('decimal')
->step('0.01')
Using mask:
->mask(fn (Forms\Components\TextInput\Mask $mask) => $mask
->numeric()
->decimalPlaces(2)
->decimalSeparator('.')
->thousandsSeparator(',')
->minValue(0)
)
Environment:
Laravel 10 Filament 3 PHP 8.2
Expected behavior: When I enter "1000", it should stay as "1000" Actual behavior: When I enter "1000", it immediately becomes "10" Question: How can I prevent Filament from truncating large numbers in a numeric TextInput field? I need to be able to enter numbers up to 999,999.99 with proper decimal support.
Upvotes: 1
Views: 273
Reputation: 21
Consider using ->live(onBlur: true) in this case. This is a common issue in Livewire, where the request is slower than the user's typing speed. Using onBlur: true can help resolve this."
https://filamentphp.com/docs/3.x/forms/advanced#reactive-fields-on-blur
Upvotes: 0