Best Way to create invoice number preview

TextInput::make('finance_invoice_start_number')
->live(onBlur: true)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The starting number for the invoice number. .'),
TextInput::make('finance_invoice_suffix')
->live(onBlur: true)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The suffix for the invoice number. For example, if the suffix is "-INV", the invoice number will be "0001-INV".'),
TextInput::make('finance_invoice_number_padding')
->live(onBlur: true)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The number of digits to pad the invoice number with. For example, if the padding is "4", the invoice number will be "0001".'),

TextInput::make('finance_invoice_start_number')
->live(onBlur: true)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The starting number for the invoice number. .'),
TextInput::make('finance_invoice_suffix')
->live(onBlur: true)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The suffix for the invoice number. For example, if the suffix is "-INV", the invoice number will be "0001-INV".'),
TextInput::make('finance_invoice_number_padding')
->live(onBlur: true)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The number of digits to pad the invoice number with. For example, if the padding is "4", the invoice number will be "0001".'),

I want to generate a preview of how the invoice number will look upon changint the field values. I can use a livewire component with alpine using this
public function getInvoiceNumberPreviewProperty()
{
$number = str_pad($this->startingNumber, $this->padding, '0', STR_PAD_LEFT);

return "{$this->prefix}{$number}{$this->suffix}";
}
public function getInvoiceNumberPreviewProperty()
{
$number = str_pad($this->startingNumber, $this->padding, '0', STR_PAD_LEFT);

return "{$this->prefix}{$number}{$this->suffix}";
}
but wondering if there is a more elegant way to do it directly in the form?
Solution:
@toeknee thanks for your help it led me in right direction! ```<?php class Invoices extends Page implements HasForms...
Jump to solution
4 Replies
toeknee
toeknee3mo ago
have a readonly invoice number field, and make each of the text inputs live? Which have an afterstate updated method that generates the invoice id and sets the readonly field?
nostrodamned
nostrodamned3mo ago
I did try
TextInput::make('finance_invoice_start_number')
->live(onBlur: true)
->afterStateUpdated(function ($state, Set $set, Get $get) {
$preview = $this->generatePreview($get);
dump('Updating start number, new preview: '.$preview);
$set('invoicePreview', $preview);
})
,

TextInput::make('finance_invoice_suffix')
->live(onBlur: true)
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('invoicePreview', $this->generatePreview($get))
)
,

TextInput::make('finance_invoice_number_padding')
->live(onBlur: true)
->numeric()
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('invoicePreview', $this->generatePreview($get))
)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The number of digits to pad the invoice number with.'),

Placeholder::make('invoicePreview')
->live()
->content(fn (Get $get) => $get('invoicePreview')),
])
TextInput::make('finance_invoice_start_number')
->live(onBlur: true)
->afterStateUpdated(function ($state, Set $set, Get $get) {
$preview = $this->generatePreview($get);
dump('Updating start number, new preview: '.$preview);
$set('invoicePreview', $preview);
})
,

TextInput::make('finance_invoice_suffix')
->live(onBlur: true)
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('invoicePreview', $this->generatePreview($get))
)
,

TextInput::make('finance_invoice_number_padding')
->live(onBlur: true)
->numeric()
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('invoicePreview', $this->generatePreview($get))
)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The number of digits to pad the invoice number with.'),

Placeholder::make('invoicePreview')
->live()
->content(fn (Get $get) => $get('invoicePreview')),
])
with this function
private function generatePreview(Get $get): string
{
$startNumber = $get('finance_invoice_start_number');
$suffix = $get('finance_invoice_suffix');
$padding = max(0, intval($get('finance_invoice_number_padding')));
$formattedNumber = str_pad($startNumber, $padding, '0', STR_PAD_LEFT);
return $formattedNumber.$suffix;
}
private function generatePreview(Get $get): string
{
$startNumber = $get('finance_invoice_start_number');
$suffix = $get('finance_invoice_suffix');
$padding = max(0, intval($get('finance_invoice_number_padding')));
$formattedNumber = str_pad($startNumber, $padding, '0', STR_PAD_LEFT);
return $formattedNumber.$suffix;
}
but it doesnt update the placeholder @toeknee
toeknee
toeknee3mo ago
It won't as it's a placeholder. We can't set placeholders. You can actually invert this, one second If you make the fields live and set the placeholder to be live, you can make the content build the invoice number?
\Filament\Forms\Components\Placeholder::make('invoice_id')
->label('Invoice ID Example')
->live()
->content(fn ($record, $get) => self::generatePreview($get)),
\Filament\Forms\Components\Placeholder::make('invoice_id')
->label('Invoice ID Example')
->live()
->content(fn ($record, $get) => self::generatePreview($get)),
I believe will work... notice get will only work on valid fields. So your method should also work if you have invoicePreview as a hidden field I believe
Solution
nostrodamned
nostrodamned3mo ago
@toeknee thanks for your help it led me in right direction!
<?php


class Invoices extends Page implements HasForms
{
...

public ?array $data = [];

public function form(Form $form): Form
{
return $form->schema(
[ TextInput::make('finance_invoice_start_number')
->live(onBlur: true)
->afterStateUpdated(function ($state, Set $set, Get $get) {
$preview = self::generatePreview($get);
dump('Updating start number, new preview: '.$preview);
$set('invoicePreview', $preview);
}),

TextInput::make('finance_invoice_suffix')
->live(onBlur: true)
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('invoicePreview', self::generatePreview($get))
)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The suffix for the invoice number.'),

TextInput::make('finance_invoice_number_padding')
->live(onBlur: true)
->numeric()
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('invoicePreview', self::generatePreview($get))
),

Placeholder::make('invoicePreview')
->live()
->content(fn (Get $get) => self::generatePreview($get)),

// ...Finance\Forms\InvoiceSettingsForm::getForm(),

])->statePath('data');

}

public static function generatePreview(Get $get): string
{
$startNumber = $get('finance_invoice_start_number');
$suffix = $get('finance_invoice_suffix');
$padding = max(0, intval($get('finance_invoice_number_padding')));
$formattedNumber = str_pad($startNumber, $padding, '0', STR_PAD_LEFT);

return $formattedNumber.$suffix;
}
}
<?php


class Invoices extends Page implements HasForms
{
...

public ?array $data = [];

public function form(Form $form): Form
{
return $form->schema(
[ TextInput::make('finance_invoice_start_number')
->live(onBlur: true)
->afterStateUpdated(function ($state, Set $set, Get $get) {
$preview = self::generatePreview($get);
dump('Updating start number, new preview: '.$preview);
$set('invoicePreview', $preview);
}),

TextInput::make('finance_invoice_suffix')
->live(onBlur: true)
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('invoicePreview', self::generatePreview($get))
)
->hintIcon('heroicon-m-question-mark-circle', tooltip: 'The suffix for the invoice number.'),

TextInput::make('finance_invoice_number_padding')
->live(onBlur: true)
->numeric()
->afterStateUpdated(fn ($state, Set $set, Get $get) => $set('invoicePreview', self::generatePreview($get))
),

Placeholder::make('invoicePreview')
->live()
->content(fn (Get $get) => self::generatePreview($get)),

// ...Finance\Forms\InvoiceSettingsForm::getForm(),

])->statePath('data');

}

public static function generatePreview(Get $get): string
{
$startNumber = $get('finance_invoice_start_number');
$suffix = $get('finance_invoice_suffix');
$padding = max(0, intval($get('finance_invoice_number_padding')));
$formattedNumber = str_pad($startNumber, $padding, '0', STR_PAD_LEFT);

return $formattedNumber.$suffix;
}
}