F
Filament6mo ago
VR

Table actions on demand

Hi guys, I need to load actions on demand. Is that possible? I want that the data to be loaded first (without any actions related to being rendered) and the actions to be computed after that, or maybe by clicking on the action group to compute all the actions available for that record. Because I have a lot of records and on each record, I have multiple actions (9-14) and each action has multiple conditions if I show the action or not. I tested with and without actions and the difference in about 30-40%. Do you guys have any insights on the matter? PS: I'm still using filament v2. Best regards, Vasi
12 Replies
toeknee
toeknee6mo ago
Please provide what you are doing for the actions to be shown. For example, you can adjust the eloquent query on the resource to include a count of relationship records which will be massively faster than calling the relationship and then count on the row itself. Example:
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
])->withCount(['activities']);
}
public static function getEloquentQuery(): Builder
{
return parent::getEloquentQuery()
->withoutGlobalScopes([
SoftDeletingScope::class,
])->withCount(['activities']);
}
->actions([
Tables\Actions\Action::make('history')
->label('')
->icon('heroicon-o-clock')
->url(fn ($record) => self::getUrl('activities', ['record' => $record->id]))
->visible(fn ($record) => $record->activities_count > 0)
->openUrlInNewTab(),
])
->actions([
Tables\Actions\Action::make('history')
->label('')
->icon('heroicon-o-clock')
->url(fn ($record) => self::getUrl('activities', ['record' => $record->id]))
->visible(fn ($record) => $record->activities_count > 0)
->openUrlInNewTab(),
])
is much quicker than if you were to do:
->actions([
Tables\Actions\Action::make('history')
->label('')
->icon('heroicon-o-clock')
->url(fn ($record) => self::getUrl('activities', ['record' => $record->id]))
->visible(fn ($record) => $record->activities->count() > 0)
->openUrlInNewTab(),
])
->actions([
Tables\Actions\Action::make('history')
->label('')
->icon('heroicon-o-clock')
->url(fn ($record) => self::getUrl('activities', ['record' => $record->id]))
->visible(fn ($record) => $record->activities->count() > 0)
->openUrlInNewTab(),
])
VR
VR6mo ago
I'm using direct TableResource protected function getTableQuery(): \Illuminate\Database\Eloquent\Builder { return Model::query(); } protected function getTableActions(): array { return [ Tables\Actions\ActionGroup::make([ Action::make('debug')... ->visible(fn($record): bool => in_array($record->status, [STATUS::STATUS]) && $this->hasPermissionTo(Permissions::PERMISSION)) ]); ]; } The problem is that I have a lot of conditions for showing the action or not, conditions to create url, permissions check, and so on... and that adds loading time when having 500k records.
DrByte
DrByte6mo ago
All all those "lot of conditions" happening in-browser (ie: defined in the Filament page in a way that creates lots of background trips to the server)? or can you push more of that logic into the backend with Gate or dynamic attributes on the model, etc?
VR
VR6mo ago
is not that is making lots of trips to the server.... the main issue for me is that for each record I have 10-15 actions, and each action has at least 1-2 permissions (which are cached) check and also some status check. The client wants to have at least 100 records per page. Doing all that logic on the first iteration adds 30% to the loading time. I was thinking if there was a way to load the actions on demand: Like creating a column named actions with a button in it, and click to render the logic for that record and show the available actions only for that record. I discovered that if I remove the ->action() function from the action itself, the actions are rendering fast, so conditions are not a problem. Is that an expected behavior? is there any other official way to call some functions without the ->action() function? Because if I remove the ->action() function then the form builder or requireCOnfirmation does not work at all.
toeknee
toeknee6mo ago
Can you provide the whole code? because there is no ->action() in any of the above
VR
VR6mo ago
even if I add an empty action() that returns only a string, each action() function add some loading time on the server. Tbh on local I don't see the diference. But here is a simple action that I use:
Action::make('comment')
->button()
->form([
TextInput::make('comment')->required()
])
->action(function (Customer $record, array $data): void {
$comment = new Comment();
$comment->user_id = \Auth::user()->id;
$comment->customer_id = $record->id;;
$comment->comment = $data['comment'] ?? null;
$comment->save();
})
->icon('heroicon-s-chat'),
Action::make('comment')
->button()
->form([
TextInput::make('comment')->required()
])
->action(function (Customer $record, array $data): void {
$comment = new Comment();
$comment->user_id = \Auth::user()->id;
$comment->customer_id = $record->id;;
$comment->comment = $data['comment'] ?? null;
$comment->save();
})
->icon('heroicon-s-chat'),
toeknee
toeknee6mo ago
Yeah I've heard this from @Tin Modric too. what remote servers are you guys running?
VR
VR6mo ago
*-memory
description: System memory
physical id: 0
size: 31GiB
*-cpu
product: Intel(R) Xeon(R) Platinum 8175M CPU @ 2.50GHz
vendor: Intel Corp.
physical id: 1
bus info: cpu@0
width: 64 bits
*-memory
description: System memory
physical id: 0
size: 31GiB
*-cpu
product: Intel(R) Xeon(R) Platinum 8175M CPU @ 2.50GHz
vendor: Intel Corp.
physical id: 1
bus info: cpu@0
width: 64 bits
Yeah, we come across this issue and really don't know the case. We may suspect that is a server issue (this is a testing server), but we can not go with we think when deploying it in production...
toeknee
toeknee6mo ago
Even still, it shouldn't have a major slow down from adding a simple empty function. Can you test a V3 instance on the same server?
VR
VR6mo ago
We can not yet... we plan that for next year because we need to upgrade also the livewire version 🙂 Yes, I agree with that, but still something not right. We build a wrapper around the actions, to require the actions on demand and the difference on the same server is large. Like with normal filament action behavior, the loading time is around 8-10 seconds, and with the actions loaded on demand is under 2 sec.
toeknee
toeknee6mo ago
Can you setup a very basic app and data to test? As you have a server with the issue it would help see if it's fixed in V3, since that is whats currently our LTS release.
VR
VR6mo ago
will try that also when time will allow it 🙂