In this article, we are going to explore how can we show infolist dynamically in laravel filament.
Click here to check the visual representation of what we are going to create.
Create a custom page
So, the first step is to create a custom page using the following command:
php artisan make:filament-page FeePaymentPage
Implement HasForms, Hastables
Since, we are having a filter on our page , so we will implement HasForms and HasTables and use their traits.
class FeePaymentPage extends Page implements HasForms, HasActions
{
use InteractsWithForms, InteractsWithActions;
protected static string $view = 'filament.admin.pages.fee-payment-page';
public $learner_id = null;
}
Learn more about filament.
Add your form and tables
If you want to add form and table on your custom page, you can add the required methods and implement the functionality. You can checkout the youtube playlist or our articles for that.
Form Code:
public function form(Form $form): Form
{
return $form
->schema([
Section::make()
->schema([
Grid::make(3)
->schema([
Select::make('class_id')
->label('Class')
->options(Classes::all()->pluck('name', 'id'))
->searchable()
->required()
->reactive()
->afterStateUpdated(function ($state) {
$this->class_id = $state;
$this->stream_id = null;
$this->learner_id = null;
$this->learnerData = null;
$this->resetTable();
}),
Select::make('stream_id')
->label('Stream')
->options(function (callable $get) {
if (!$get('class_id')) {
return [];
}
return Stream::where('class_id', $get('class_id'))
->pluck('name', 'id');
})
->searchable()
->visible(fn (callable $get) => $get('class_id'))
->reactive()
->afterStateUpdated(function ($state) {
$this->stream_id = $state;
$this->learner_id = null;
$this->learnerData = null;
$this->resetTable();
}),
Select::make('learner_id')
->label('Student')
->options(function (callable $get) {
if (!$get('stream_id')) {
return [];
}
return Learner::where('stream_id', $get('stream_id'))
->get()
->pluck('name', 'id');
})
->searchable()
->visible(fn (callable $get) => $get('stream_id'))
->reactive()
->afterStateUpdated(function ($state) {
$this->learner_id = $state;
$this->loadLearnerData();
$this->resetTable();
}),
]),
])
->columnSpan('full'),
]);
}
public function loadLearnerData(): void
{
if (!$this->learner_id) {
return;
}
$this->learnerData = Learner::with(['stream', 'stream.class',"financialProfile"])->find($this->learner_id);
}
Table
public function table(Table $table): Table
{
return $table
->query(function () {
if (!$this->learner_id) {
return Transaction::query()->whereNull('id'); // Empty query if no learner selected
}
$query = Transaction::query()
->where('learner_id', $this->learner_id)
->where('transaction_type',Transaction::DEBIT);
return $query;
})
->columns([
TextColumn::make('transaction_date')
->label('Date')
->date('d/m/Y')
->sortable(),
TextColumn::make('feeStructure.name')
->label('Fee Structure')
->searchable(),
TextColumn::make('feeCategory.name')
->label('Fee Category')
->searchable(),
TextColumn::make('amount')
->label('Amount')
->sortable()
->badge(),
BadgeColumn::make('status')
->colors([
'warning' => 'Pending',
'success' => 'Completed',
'danger' => 'Failed',
]),
TextColumn::make('payment_method')
->label('Payment Method'),
TextColumn::make('remarks')
->label('Remarks')
->limit(20),
])
->filters([
SelectFilter::make('status')
->default(Transaction::PENDING_STATUS)
->options([
'Pending' => 'Pending',
'Completed' => 'Completed',
'Failed' => 'Failed',
]),
SelectFilter::make('transaction_type')
->options([
'Debit' => 'Debit',
'Credit' => 'Credit',
]),
])
->actions([
])
->bulkActions([])
->emptyStateHeading('No transactions found')
->emptyStateDescription('Select a student to view their transactions.')
->poll('60s');
}
Modify your blade component to use form, table and your dynamic custom infolist
<x-filament-panels::page>
<div>
{{ $this->form }}
</div>
@if($learnerData)
<div class="mt-8 rounded-xl shadow p-6">
<h2 class="text-xl font-bold mb-4">Student Information</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-4">
<div>
<h3 class="text-gray-500 font-medium">Name</h3>
<p class="text-lg">{{ $learnerData->name }}</p>
</div>
<div>
<h3 class="text-gray-500 font-medium">Class</h3>
<p class="text-lg">{{ $learnerData->stream?->class?->name }}</p>
</div>
<div>
<h3 class="text-gray-500 font-medium">Stream</h3>
<p class="text-lg">{{ $learnerData->stream?->name }}</p>
</div>
<div>
<h3 class="text-gray-500 font-medium">Total Outstandings</h3>
<p class="text-lg">{{ $learnerData->financialProfile?->current_outstanding_balance }}</p>
</div>
</div>
</div>
@endif
<div class="mt-8">
{{ $this->table }}
</div>
</x-filament:pages>
So , in this way you can create a dynamic infolist page on your custom page.