Filament Resource: Repeating Code in Static Function to Avoid Duplication

2024-12-05

What if you have repeating code in your Filament resource? For example, you have the same calculations for more than one input? Let's see how we can extract this code into a separate static function.


In this example, we have the same calculations for total cost, repeated on change of three different input fields. How to avoid that repetition?

Here is the initial code for the form.

use Filament\Forms;
use Filament\Forms\Form;
 
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('quantity')
->numeric()
->required()
->live(onBlur: true)
->afterStateUpdated(fn(Forms\Set $set, Forms\Get $get, ?int $state) =>
$set('total_cost', $get('unit_cost') * $get('quantity') * (1 + $get('tax') / 100));
),
Forms\Components\TextInput::make('tax')
->numeric()
->suffix('%')
->required()
->live(onBlur: true)
->afterStateUpdated(fn(Forms\Set $set, Forms\Get $get, ?int $state) =>
$set('total_cost', $get('unit_cost') * $get('quantity') * (1 + $get('tax') / 100));
),
Forms\Components\TextInput::make('unit_cost')
->numeric()
->suffix('USD')
->required()
->live(onBlur: true)
->afterStateUpdated(fn(Forms\Set $set, Forms\Get $get, ?int $state) =>
$set('total_cost', $get('unit_cost') * $get('quantity') * (1 + $get('tax') / 100));
),
Forms\Components\TextInput::make('total_cost')
->numeric()
->suffix('USD')
->required()
->disabled()
->dehydrated(),
]);
}

We can extract the repeating code part using a separate static method.

class OrderResource extends Resource
{
// ...
 
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('quantity')
->numeric()
->required()
->live(onBlur: true)
->afterStateUpdated(fn(Forms\Set $set, Forms\Get $get, ?int $state) =>
$set('total_cost', $get('unit_cost') * $get('quantity') * (1 + $get('tax') / 100));
self::updateTotalCost($get, $set)
),
Forms\Components\TextInput::make('tax')
->numeric()
->suffix('%')
->required()
->live(onBlur: true)
->afterStateUpdated(fn(Forms\Set $set, Forms\Get $get, ?int $state) =>
$set('total_cost', $get('unit_cost') * $get('quantity') * (1 + $get('tax') / 100));
self::updateTotalCost($get, $set)
),
Forms\Components\TextInput::make('unit_cost')
->numeric()
->suffix('USD')
->required()
->live(onBlur: true)
->afterStateUpdated(fn(Forms\Set $set, Forms\Get $get, ?int $state) =>
$set('total_cost', $get('unit_cost') * $get('quantity') * (1 + $get('tax') / 100));
self::updateTotalCost($get, $set)
),
Forms\Components\TextInput::make('total_cost')
->numeric()
->suffix('USD')
->required()
->disabled()
->dehydrated(),
]);
}
 
// ...
 
private static function updateTotalCost(Forms\Get $get, Forms\Set $set): void
{
$set('total_cost', $get('unit_cost') * $get('quantity') * (1 + $get('tax') / 100));
}
}

Now, we don't repeat code, and if you need to add more logic, you will need to add it only in one place, which reduces the chance of missing something.

Important to note that the function should be static because the form() method is also static, so we can't call it like $this->.... We use the self:: syntax, instead.

A few of our Premium Examples: