Courses

Filament 3 From Scratch: Practical Course

Restrict Add/Edit/Delete Actions and Buttons

Summary of this lesson:
- Restricting CRUD actions
- Implementing user permissions
- Using Laravel policies
- Managing access control

In this lesson, let's look at simple ways to hide action buttons from the Filament table.


Restrict Create/Delete on Users

Let's imagine we have a User Management section, but we can't create a new user (they register themselves) or delete the existing one (for history archive reasons). The only thing we can do is edit the user's data.

So, I've generated a resource:

php artisan make:filament-resource User

And added a few columns to the form/table:

app/Filament/Resources/UserResource.php:

class UserResource extends Resource
{
public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name'),
Forms\Components\TextInput::make('email')
->email(),
]);
}
 
public static function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('email'),
Tables\Columns\TextColumn::make('created_at')
->dateTime(),
])
->actions([
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
])
->emptyStateActions([
Tables\Actions\CreateAction::make(),
]);
}
 
public static function getPages(): array
{
return [
'index' => Pages\ListUsers::route('/'),
'create' => Pages\CreateUser::route('/create'),
'edit' => Pages\EditUser::route('/{record}/edit'),
];
}
}

Visually it looks like this:

Now, let's remove the ability to Add and Delete users.


Restrict Adding New Records

To hide the Create form and all links to it, we need to make four changes:

Step 1. Resource method getPages(): delete the create page.

return [
'index' => Pages\ListUsers::route('/'),
'create' => Pages\CreateUser::route('/create'),
'edit' => Pages\EditUser::route('/{record}/edit'),
];

Step 2. In the Resource Table, remove the CreateAction::make() in the ->emptyStateActions(). This button is visible if the table has 0 records.

return $table
// ...
->emptyStateActions([
Tables\Actions\CreateAction::make(),
]);

Step 3. File app/Filament/Resources/UserResource/Pages/ListUsers.php: remove the Header Action to hide the button on the top-right.

class ListUsers extends ListRecords
{
protected function getHeaderActions(): array
{
return [
Actions\CreateAction::make(),
];
}
}

Step 4. Physically delete the file app/Filament/Resources/UserResource/Pages/CreateUser.php.

Now, the button is gone:

And even if you manually visit the URL /admin/users/create, you will get a "404 Not Found". Great.


Restrict Deleting Records

So, we want to disable the Delete button. But wait, it seems we haven't even shown it on the table, so we don't have to do anything!

Wrong.

There are two places where the users can still be deleted.

Step 1. Remove "Bulk Delete".

If you tick any checkbox in the table and choose "Bulk actions", you will see this:

To disable that, you need to delete the DeleteBulkAction::make(), or even empty the whole array of bulkActions():

return $table
// ...
->bulkActions([
Tables\Actions\BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
]),
])

Interestingly, if Filament doesn't detect any Bulk Actions, it won't even show the column with checkboxes.

Step 2. Remove "Delete" from the Edit form.

Not many people use this feature, but the Edit form also contains the Delete button.

Filament allows you to easily show/hide it, similarly to other buttons. In the file app/Filament/Resources/UserResource/Pages/EditUser.php, remove it from the array of header actions:

class EditUser extends EditRecord
{
protected function getHeaderActions(): array
{
return [
Actions\DeleteAction::make(),
];
}
}

Hide Edit Button on Condition

Finally, let's try to hide even the Edit button if the user is not an administrator.

Let's say that in the database, we have a column users.is_admin with values of 1 and 0.

First, the wrong way. We could try to show/hide a button with the condition:

return $table
->actions([
Tables\Actions\EditAction::make()
->visible(auth()->user()->is_admin),
])

Now the button is gone if you're not an admin.

But if you launch the URL /admin/users/1/edit manually... you can still access it!

So, the correct way is to validate the access on the back-end using Laravel Policies, which Filament would automatically detect.

So we delete the ->visible() condition above and instead do this:

php artisan make:policy UserPolicy --model=User

And then we need only one method inside:

app/Policies/UserPolicy.php:

namespace App\Policies;
 
use App\Models\User;
 
class UserPolicy
{
public function update(User $user, User $model): bool
{
return $user->is_admin;
}
}

And that's it. We don't need to change anything in the UserResource class. If the user is not an administrator, the button will be invisible, and the direct URL /admin/users/1/edit will throw an error page of "403 Forbidden".

avatar

a nice addition is how to add softdeletes to the action. for archive reasons you probably dont want to delete the complete entity but softdeletes/archive however would be a great addition

avatar

Wouldn't you just add the SoftDeletes trait to the model and add the softdeletes() method to the migration?

avatar
You can use Markdown
avatar

How to hide a create button depends on user role?

avatar

You can use blade policy checks:

https://laravel.com/docs/11.x/authorization#via-blade-templates

avatar
You can use Markdown
avatar
You can use Markdown