Conditionally add and update relations

Currently I got this situation. A user can have only 1 shipping address and only 1 billing address. In Filament's admin panel's user form, admin can change user's info. However I want to set restrictions, so that admin cant give a user >1 address of type shipping, and cant give a user >1 address of type billing. That also implies that when the user already got 1 billing address, the admin can't change that user's shipping address to type=billing. How can something like that be done?
Solution:
Create a policy according to the laravel docs then handle the conditions in each method based on your apps authorization. Filament defaults to Laravel’s policies to handle model authorization. https://laravel.com/docs/11.x/authorization#creating-policies
Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.
Jump to solution
13 Replies
igorclauss
igorclauss2mo ago
In most cases you can pass Closures or Callables to filament methods.
atabegruslan
atabegruslan2mo ago
Yes. But a more detailed answer please
LeandroFerreira
LeandroFerreira2mo ago
Please provide some code you are using
atabegruslan
atabegruslan2mo ago
Here:
class UserResource extends Resource
{
protected static ?string $model = User::class;

public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Section::make()->schema([
// ...
]),
Forms\Components\Section::make()->schema([
Forms\Components\Repeater::make('addresses')
->relationship()
->schema([
// Todo: can only chose 1 of type shipping and 1 of type billing <<--------*********
Forms\Components\TextInput::make('email'),
Forms\Components\TextInput::make('address_line_1'),
Forms\Components\TextInput::make('city'),
Forms\Components\TextInput::make('zip_code'),
Forms\Components\TextInput::make('state'),
])
->addable(false) // Todo: Can only add 1 shipping and 1 billing <<--------*********
->itemLabel(fn (array $state) => $state['type'])
])
]);
}
class UserResource extends Resource
{
protected static ?string $model = User::class;

public static function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Section::make()->schema([
// ...
]),
Forms\Components\Section::make()->schema([
Forms\Components\Repeater::make('addresses')
->relationship()
->schema([
// Todo: can only chose 1 of type shipping and 1 of type billing <<--------*********
Forms\Components\TextInput::make('email'),
Forms\Components\TextInput::make('address_line_1'),
Forms\Components\TextInput::make('city'),
Forms\Components\TextInput::make('zip_code'),
Forms\Components\TextInput::make('state'),
])
->addable(false) // Todo: Can only add 1 shipping and 1 billing <<--------*********
->itemLabel(fn (array $state) => $state['type'])
])
]);
}
(Updated. Sorry about the screenshot earlier. I replaced that image attachment with text code now)
toeknee
toeknee2mo ago
Please read #✅┊rules on how to provide code.
atabegruslan
atabegruslan2mo ago
Sorry I am out and I only have my phone
awcodes
awcodes2mo ago
This would normally be handled by a laravel policy. Filament is still just laravel under the hood.
atabegruslan
atabegruslan2mo ago
How exactly do you do that? Something more specific please
Solution
awcodes
awcodes2mo ago
Create a policy according to the laravel docs then handle the conditions in each method based on your apps authorization. Filament defaults to Laravel’s policies to handle model authorization. https://laravel.com/docs/11.x/authorization#creating-policies
Laravel - The PHP Framework For Web Artisans
Laravel is a PHP web application framework with expressive, elegant syntax. We’ve already laid the foundation — freeing you to create without sweating the small things.
atabegruslan
atabegruslan2mo ago
Thank you
atabegruslan
atabegruslan2mo ago
Actually, policy is only half the answer. Normally, you create a policy, then you apply it in controller method, like $this->authorize('action', $modelInstance); But Filament have its own controllers. It doesnt go thru any of the controllers that I wrote. Hence in this situation, how can policy (or any type of pre-saving checks) be done upon the click of the add/delete/edit buttons?
atabegruslan
atabegruslan2mo ago
No description
Zen Nitiruj
Zen Nitiruj2mo ago
You can add ->authorize() in your action component. In this case, you are using Repeater you can customize addAction by follow with https://filamentphp.com/docs/3.x/forms/fields/repeater ->addAction(fn($action)=> $action->authorize(...
Want results from more Discord servers?
Add your server