Lazy load table column

I had a table where one of the columns took a long time to compute. It caused the table to load longer because of that one column. Can the table builder implement some sort of lazy loading for columns in the table without implementing deferLoading() for the table as a whole? I appreciate all the answers and help, Thank you.
11 Replies
CodeWithDennis
CodeWithDennis2mo ago
Can you show me that column?
Mohamed Ayaou
Mohamed Ayaou2mo ago
You may not lazy load the column but maybe the computing process itself, but I think you will need some frontend customization here something like that.
Garadit
GaraditOP2mo ago
// This is the column
Tables\Columns\TextColumn::make('status')
->badge()
->color(fn (string $state): string => match ($state) {
'Pending' => 'gray',
'SPK Created' => 'primary',
'Partially Printed' => 'info',
'Fully Printed' => 'success',
'Delivery Order Created' => 'info',
'Invoice Created' => 'success',
})
->icon(fn (string $state): string => match ($state) {
'Pending' => 'heroicon-o-clock',
'SPK Created' => 'heroicon-o-cog',
'Partially Printed' => 'heroicon-o-printer',
'Fully Printed' => 'heroicon-o-printer',
'Delivery Order Created' => 'heroicon-o-truck',
'Invoice Created' => 'heroicon-o-printer',
}),

// This is the model attributes
public function getStatusAttribute()
{
$orderProducts = $this->orderProducts;
$statuses = $orderProducts->pluck('status');

switch (true) {
case $this->invoices()->exists():
return 'Invoice Created';

case $this->deliveryOrders()->exists():
return 'Delivery Order Created';

case $statuses->every(fn ($status) => $status === 'Printed'):
return 'Fully Printed';

case $statuses->contains('Printed'):
return 'Partially Printed';

case $this->spks()->exists():
return 'SPK Created';

default:
return 'Pending';
}
}
// This is the column
Tables\Columns\TextColumn::make('status')
->badge()
->color(fn (string $state): string => match ($state) {
'Pending' => 'gray',
'SPK Created' => 'primary',
'Partially Printed' => 'info',
'Fully Printed' => 'success',
'Delivery Order Created' => 'info',
'Invoice Created' => 'success',
})
->icon(fn (string $state): string => match ($state) {
'Pending' => 'heroicon-o-clock',
'SPK Created' => 'heroicon-o-cog',
'Partially Printed' => 'heroicon-o-printer',
'Fully Printed' => 'heroicon-o-printer',
'Delivery Order Created' => 'heroicon-o-truck',
'Invoice Created' => 'heroicon-o-printer',
}),

// This is the model attributes
public function getStatusAttribute()
{
$orderProducts = $this->orderProducts;
$statuses = $orderProducts->pluck('status');

switch (true) {
case $this->invoices()->exists():
return 'Invoice Created';

case $this->deliveryOrders()->exists():
return 'Delivery Order Created';

case $statuses->every(fn ($status) => $status === 'Printed'):
return 'Fully Printed';

case $statuses->contains('Printed'):
return 'Partially Printed';

case $this->spks()->exists():
return 'SPK Created';

default:
return 'Pending';
}
}
What @Mohamed Ayaou said is right, it is necessary to optimize the computing process itself. But I need to adjust to the old code that is already running, so I can't do too much. The 'status' attribute itself takes a long time because it has to check every condition, especially in the every function. It might be faster if the every process could be done in parallel, unfortunately this is PHP which is blocking by default.
CodeWithDennis
CodeWithDennis2mo ago
Thats not true, we have the concurrency helper. https://www.youtube.com/watch?v=PMEQ93kBc7U
CodeWithDennis
CodeWithDennis2mo ago
But looking at this code it might not be a great approach 😅 You should check debugbar and check how many queries are executed.
Mohamed Ayaou
Mohamed Ayaou2mo ago
Thanks, but concurrency is great when the we have an issue with multiple long running tasks not with one long task what I meant with frontend customization eg. is to load the column empty and then fetch its data later as any lazy loading approach Maybe it won't be that complex with livewire native support from filament?
CodeWithDennis
CodeWithDennis2mo ago
Yes, but was just refering to your statement. I think you should take a look at your getStatusAttribute logic.
Mohamed Ayaou
Mohamed Ayaou2mo ago
Thank you, I just want to say an idea about the lazy loading approach on a single column, it maybe done via some livewire tricks, or to fetch the column data with JS on the frontend manually, you know that more than me
Garadit
GaraditOP2mo ago
Thanks @CodeWithDennis . Bad queries are the main problem, right in getStatusAttribute. It calls more than 1000 queries, like, that's huge. Now that I'm using raw queries, the performance has improved significantly. Yes, Thanks for the insight @Mohamed Ayaou . I think the lazy load approach is still needed, especially when calling multiple APIs and running huge computed data. I'm still thinking about how to implement it, like we apply toggleable() but it triggers automatically when the table is rendered.
CodeWithDennis
CodeWithDennis2mo ago
You don't need raw queries you can still do it with ORM but just needs to know how.
Mohamed Ayaou
Mohamed Ayaou2mo ago
Maybe I got an idea using livewire, just use a custom livewire column with an empty value with a timer in the frontend to trigger a livewire code to start the data computing and displaying it, so the column is rendered empty and then just auto-update itself just an idea.
Want results from more Discord servers?
Add your server