公告: 旧版文档请移步 -> http://v2.laravel-filament.cn/docs

Languages

Version

Theme

Panel Builder - Resources

Managing relationships

Choosing the right tool for the job

Filament provides many ways to manage relationships in the app. Which feature you should use depends on the type of relationship you are managing, and which UI you are looking for.

Relation managers - interactive tables underneath your resource forms

These are compatible with HasMany, HasManyThrough, BelongsToMany, MorphMany and MorphToMany relationships.

Relation managers are interactive tables that allow administrators to list, create, attach, associate, edit, detach, dissociate and delete related records without leaving the resource's Edit or View page.

Select & checkbox list - choose from existing records or create a new one

These are compatible with BelongsTo, MorphTo and BelongsToMany relationships.

Using a select, users will be able to choose from a list of existing records. You may also add a button that allows you to create a new record inside a modal, without leaving the page.

When using a BelongsToMany relationship with a select, you'll be able to select multiple options, not just one. Records will be automatically added to your pivot table when you submit the form. If you wish, you can swap out the multi-select dropdown with a simple checkbox list. Both components work in the same way.

These are compatible with HasMany and MorphMany relationships.

Repeaters are standard form components, which can render a repeatable set of fields infinitely. They can be hooked up to a relationship, so records are automatically read, created, updated, and deleted from the related table. They live inside the main form schema, and can be used inside resource pages, as well as nesting within action modals.

From a UX perspective, this solution is only suitable if your related model only has a few fields. Otherwise, the form can get very long.

Layout form components - saving form fields to a single relationship

These are compatible with BelongsTo, HasOne and MorphOne relationships.

All layout form components (Grid, Section, Fieldset, etc.) have a relationship() method. When you use this, all fields within that layout are saved to the related model instead of the owner's model:

use Filament\Forms\Components\Fieldset;
use Filament\Forms\Components\FileUpload;
use Filament\Forms\Components\Textarea;
use Filament\Forms\Components\TextInput;
 
Fieldset::make('Metadata')
->relationship('metadata')
->schema([
TextInput::make('title'),
Textarea::make('description'),
FileUpload::make('image'),
])

In this example, the title, description and image are automatically loaded from the metadata relationship, and saved again when the form is submitted. If the metadata record does not exist, it is automatically created.

This feature is explained more in depth in the Forms documentation. Please visit that page for more information about how to use it.

Creating a relation manager

Filament Laracasts
Relation Managers
Watch the Rapid Laravel Development with Filament series on Laracasts - it will teach you the basics of adding relation managers to Filament resources.
Dan Harrin
Dan Harrin
Instructor

To create a relation manager, you can use the make:filament-relation-manager command:

php artisan make:filament-relation-manager CategoryResource posts title
  • CategoryResource is the name of the resource class for the owner (parent) model.
  • posts is the name of the relationship you want to manage.
  • title is the name of the attribute that will be used to identify posts.

This will create a CategoryResource/RelationManagers/PostsRelationManager.php file. This contains a class where you are able to define a form and table for your relation manager:

use Filament\Forms;
use Filament\Forms\Form;
use Filament\Tables;
use Filament\Tables\Table;
 
public function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('title')->required(),
// ...
]);
}
 
public function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('title'),
// ...
]);
}

You must register the new relation manager in your resource's getRelations() method:

public static function getRelations(): array
{
return [
RelationManagers\PostsRelationManager::class,
];
}

Once a table and form have been defined for the relation manager, visit the Edit or View page of your resource to see it in action.

Read-only mode

Relation managers are usually displayed on either the Edit or View page of a resource. On the View page, Filament will automatically hide all actions that modify the relationship, such as create, edit, and delete. We call this "read-only mode", and it is there by default to preserve the read-only behavior of the View page. However, you can disable this behavior, by overriding the isReadOnly() method on the relation manager class to return false all the time:

public function isReadOnly(): bool
{
return false;
}

Alternatively, if you hate this functionality, you can disable it for all relation managers at once in the panel configuration:

use Filament\Panel;
 
public function panel(Panel $panel): Panel
{
return $panel
// ...
->readOnlyRelationManagersOnResourceViewPagesByDefault(false);
}

Unconventional inverse relationship names

For inverse relationships that do not follow Laravel's naming guidelines, you may wish to use the inverseRelationship() method on the table:

use Filament\Tables;
use Filament\Tables\Table;
 
public function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('title'),
// ...
])
->inverseRelationship('section'); // Since the inverse related model is `Category`, this is normally `category`, not `section`.
}

Handling soft deletes

By default, you will not be able to interact with deleted records in the relation manager. If you'd like to add functionality to restore, force delete and filter trashed records in your relation manager, use the --soft-deletes flag when generating the relation manager:

php artisan make:filament-relation-manager CategoryResource posts title --soft-deletes

You can find out more about soft deleting here.

Related records will be listed in a table. The entire relation manager is based around this table, which contains actions to create, edit, attach / detach, associate / dissociate, and delete records.

You may use any features of the Table Builder to customize relation managers.

Listing with pivot attributes

For BelongsToMany and MorphToMany relationships, you may also add pivot table attributes. For example, if you have a TeamsRelationManager for your UserResource, and you want to add the role pivot attribute to the table, you can use:

use Filament\Tables;
 
public function table(Table $table): Table
{
return $table
->columns([
Tables\Columns\TextColumn::make('name'),
Tables\Columns\TextColumn::make('role'),
]);
}

Please ensure that any pivot attributes are listed in the withPivot() method of the relationship and inverse relationship.

Creating with pivot attributes

For BelongsToMany and MorphToMany relationships, you may also add pivot table attributes. For example, if you have a TeamsRelationManager for your UserResource, and you want to add the role pivot attribute to the create form, you can use:

use Filament\Forms;
use Filament\Forms\Form;
 
public function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('role')->required(),
// ...
]);
}

Please ensure that any pivot attributes are listed in the withPivot() method of the relationship and inverse relationship.

Customizing the CreateAction

To learn how to customize the CreateAction, including mutating the form data, changing the notification, and adding lifecycle hooks, please see the Actions documentation.

Editing with pivot attributes

For BelongsToMany and MorphToMany relationships, you may also edit pivot table attributes. For example, if you have a TeamsRelationManager for your UserResource, and you want to add the role pivot attribute to the edit form, you can use:

use Filament\Forms;
use Filament\Forms\Form;
 
public function form(Form $form): Form
{
return $form
->schema([
Forms\Components\TextInput::make('name')->required(),
Forms\Components\TextInput::make('role')->required(),
// ...
]);
}

Please ensure that any pivot attributes are listed in the withPivot() method of the relationship and inverse relationship.

Customizing the EditAction

To learn how to customize the EditAction, including mutating the form data, changing the notification, and adding lifecycle hooks, please see the Actions documentation.

Attaching and detaching records

Filament is able to attach and detach records for BelongsToMany and MorphToMany relationships.

When generating your relation manager, you may pass the --attach flag to also add AttachAction, DetachAction and DetachBulkAction to the table:

php artisan make:filament-relation-manager CategoryResource posts title --attach

Alternatively, if you've already generated your resource, you can just add the actions to the $table arrays:

use Filament\Tables;
use Filament\Tables\Table;
 
public function table(Table $table): Table
{
return $table
->columns([
// ...
])
->headerActions([
// ...
Tables\Actions\AttachAction::make(),
])
->actions([
// ...
Tables\Actions\DetachAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
// ...
Tables\Actions\DetachBulkAction::make(),
]),
]);
}

Preloading the attachment modal select options

By default, as you search for a record to attach, options will load from the database via AJAX. If you wish to preload these options when the form is first loaded instead, you can use the preloadRecordSelect() method of AttachAction:

use Filament\Tables\Actions\AttachAction;
 
AttachAction::make()
->preloadRecordSelect()

Attaching with pivot attributes

When you attach record with the Attach button, you may wish to define a custom form to add pivot attributes to the relationship:

use Filament\Forms;
use Filament\Tables\Actions\AttachAction;
 
AttachAction::make()
->form(fn (AttachAction $action): array => [
$action->getRecordSelect(),
Forms\Components\TextInput::make('role')->required(),
])

In this example, $action->getRecordSelect() returns the select field to pick the record to attach. The role text input is then saved to the pivot table's role column.

Please ensure that any pivot attributes are listed in the withPivot() method of the relationship and inverse relationship.

Scoping the options to attach

You may want to scope the options available to AttachAction:

use Filament\Tables\Actions\AttachAction;
use Illuminate\Database\Eloquent\Builder;
 
AttachAction::make()
->recordSelectOptionsQuery(fn (Builder $query) => $query->whereBelongsTo(auth()->user()))

Searching the options to attach across multiple columns

By default, the options available to AttachAction will be searched in the recordTitleAttribute() of the table. If you wish to search across multiple columns, you can use the recordSelectSearchColumns() method:

use Filament\Tables\Actions\AttachAction;
 
AttachAction::make()
->recordSelectSearchColumns(['title', 'description'])

Attaching multiple records

The multiple() method on the AttachAction component allows you to select multiple values:

use Filament\Tables\Actions\AttachAction;
 
AttachAction::make()
->multiple()

Customizing the select field in the attached modal

You may customize the select field object that is used during attachment by passing a function to the recordSelect() method:

use Filament\Forms\Components\Select;
use Filament\Tables\Actions\AttachAction;
 
AttachAction::make()
->recordSelect(
fn (Select $select) => $select->placeholder('Select a post'),
)

Handling duplicates

By default, you will not be allowed to attach a record more than once. This is because you must also set up a primary id column on the pivot table for this feature to work.

Please ensure that the id attribute is listed in the withPivot() method of the relationship and inverse relationship.

Finally, add the allowDuplicates() method to the table:

public function table(Table $table): Table
{
return $table
->allowDuplicates();
}

Associating and dissociating records

Filament is able to associate and dissociate records for HasMany and MorphMany relationships.

When generating your relation manager, you may pass the --associate flag to also add AssociateAction, DissociateAction and DissociateBulkAction to the table:

php artisan make:filament-relation-manager CategoryResource posts title --associate

Alternatively, if you've already generated your resource, you can just add the actions to the $table arrays:

use Filament\Tables;
use Filament\Tables\Table;
 
public function table(Table $table): Table
{
return $table
->columns([
// ...
])
->headerActions([
// ...
Tables\Actions\AssociateAction::make(),
])
->actions([
// ...
Tables\Actions\DissociateAction::make(),
])
->bulkActions([
Tables\Actions\BulkActionGroup::make([
// ...
Tables\Actions\DissociateBulkAction::make(),
]),
]);
}

Preloading the associate modal select options

By default, as you search for a record to associate, options will load from the database via AJAX. If you wish to preload these options when the form is first loaded instead, you can use the preloadRecordSelect() method of AssociateAction:

use Filament\Tables\Actions\AssociateAction;
 
AssociateAction::make()
->preloadRecordSelect()

Scoping the options to associate

You may want to scope the options available to AssociateAction:

use Filament\Tables\Actions\AssociateAction;
use Illuminate\Database\Eloquent\Builder;
 
AssociateAction::make()
->recordSelectOptionsQuery(fn (Builder $query) => $query->whereBelongsTo(auth()->user()))

Searching the options to associate across multiple columns

By default, the options available to AssociateAction will be searched in the recordTitleAttribute() of the table. If you wish to search across multiple columns, you can use the recordSelectSearchColumns() method:

use Filament\Tables\Actions\AssociateAction;
 
AssociateAction::make()
->recordSelectSearchColumns(['title', 'description'])

Associating multiple records

The multiple() method on the AssociateAction component allows you to select multiple values:

use Filament\Tables\Actions\AssociateAction;
 
AssociateAction::make()
->multiple()

Customizing the select field in the associate modal

You may customize the select field object that is used during association by passing a function to the recordSelect() method:

use Filament\Forms\Components\Select;
use Filament\Tables\Actions\AssociateAction;
 
AssociateAction::make()
->recordSelect(
fn (Select $select) => $select->placeholder('Select a post'),
)

When generating your relation manager, you may pass the --view flag to also add a ViewAction to the table:

php artisan make:filament-relation-manager CategoryResource posts title --view

Alternatively, if you've already generated your relation manager, you can just add the ViewAction to the $table->actions() array:

use Filament\Tables;
use Filament\Tables\Table;
 
public function table(Table $table): Table
{
return $table
->columns([
// ...
])
->actions([
Tables\Actions\ViewAction::make(),
// ...
]);
}

By default, you will not be able to interact with deleted records in the relation manager. If you'd like to add functionality to restore, force delete and filter trashed records in your relation manager, use the --soft-deletes flag when generating the relation manager:

php artisan make:filament-relation-manager CategoryResource posts title --soft-deletes

Alternatively, you may add soft deleting functionality to an existing relation manager:

use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
 
public function table(Table $table): Table
{
return $table
->modifyQueryUsing(fn (Builder $query) => $query->withoutGlobalScopes([
SoftDeletingScope::class,
]))
->columns([
// ...
])
->filters([
Tables\Filters\TrashedFilter::make(),
// ...
])
->actions([
Tables\Actions\DeleteAction::make(),
Tables\Actions\ForceDeleteAction::make(),
Tables\Actions\RestoreAction::make(),
// ...
])
->bulkActions([
BulkActionGroup::make([
Tables\Actions\DeleteBulkAction::make(),
Tables\Actions\ForceDeleteBulkAction::make(),
Tables\Actions\RestoreBulkAction::make(),
// ...
]),
]);
}

Customizing the DeleteAction

To learn how to customize the DeleteAction, including changing the notification and adding lifecycle hooks, please see the Actions documentation.

The ImportAction can be added to the header of a relation manager to import records. In this case, you probably want to tell the importer which owner these new records belong to. You can use import options to pass through the ID of the owner record:

ImportAction::make()
->importer(ProductImporter::class)
->options(['categoryId' => $this->getOwnerRecord()->getKey()])

Now, in the importer class, you can associate the owner in a one-to-many relationship with the imported record:

public function resolveRecord(): ?Product
{
$product = Product::firstOrNew([
'sku' => $this->data['sku'],
]);
$product->category()->associate($this->options['categoryId']);
return $product;
}

Alternatively, you can attach the record in a many-to-many relationship using the afterSave() hook of the importer:

protected function afterSave(): void
{
$this->record->categories()->syncWithoutDetaching([$this->options['categoryId']]);
}

Accessing the relationship's owner record

Relation managers are Livewire components. When they are first loaded, the owner record (the Eloquent record which serves as a parent - the main resource model) is saved into a property. You can read this property using:

$this->getOwnerRecord()

However, if you're inside a static method like form() or table(), $this isn't accessible. So, you may use a callback to access the $livewire instance:

use Filament\Forms;
use Filament\Forms\Form;
use Filament\Resources\RelationManagers\RelationManager;
 
public function form(Form $form): Form
{
return $form
->schema([
Forms\Components\Select::make('store_id')
->options(function (RelationManager $livewire): array {
return $livewire->getOwnerRecord()->stores()
->pluck('name', 'id')
->toArray();
}),
// ...
]);
}

All methods in Filament accept a callback which you can access $livewire->ownerRecord in.

Grouping relation managers

You may choose to group relation managers together into one tab. To do this, you may wrap multiple managers in a RelationGroup object, with a label:

use Filament\Resources\RelationManagers\RelationGroup;
 
public static function getRelations(): array
{
return [
// ...
RelationGroup::make('Contacts', [
RelationManagers\IndividualsRelationManager::class,
RelationManagers\OrganizationsRelationManager::class,
]),
// ...
];
}

Conditionally showing relation managers

By default, relation managers will be visible if the viewAny() method for the related model policy returns true.

You may use the canViewForRecord() method to determine if the relation manager should be visible for a specific owner record and page:

use Illuminate\Database\Eloquent\Model;
 
public static function canViewForRecord(Model $ownerRecord, string $pageClass): bool
{
return $ownerRecord->status === Status::Draft;
}

Combining the relation manager tabs with the form

On the Edit or View page class, override the hasCombinedRelationManagerTabsWithContent() method:

public function hasCombinedRelationManagerTabsWithContent(): bool
{
return true;
}

Setting an icon for the form tab

On the Edit or View page class, override the getContentTabIcon() method:

public function getContentTabIcon(): ?string
{
return 'heroicon-m-cog';
}

Setting the position of the form tab

By default, the form tab is rendered before the relation tabs. To render it after, you can override the getContentTabPosition() method on the Edit or View page class:

use Filament\Resources\Pages\ContentTabPosition;
 
public function getContentTabPosition(): ?ContentTabPosition
{
return ContentTabPosition::After;
}

Adding badges to relation manager tabs

You can add a badge to a relation manager tab by setting the $badge property:

protected static ?string $badge = 'new';

Alternatively, you can override the getBadge() method:

use Illuminate\Database\Eloquent\Model;
 
public static function getBadge(Model $ownerRecord, string $pageClass): ?string
{
return static::$badge;
}

Or, if you are using a relation group, you can use the badge() method:

use Filament\Resources\RelationManagers\RelationGroup;
 
RelationGroup::make('Contacts', [
// ...
])->badge('new');

Changing the color of relation manager tab badges

If a badge value is defined, it will display using the primary color by default. To style the badge contextually, set the $badgeColor to either danger, gray, info, primary, success or warning:

protected static ?string $badgeColor = 'danger';

Alternatively, you can override the getBadgeColor() method:

use Illuminate\Database\Eloquent\Model;
 
public static function getBadgeColor(Model $ownerRecord, string $pageClass): ?string
{
return 'danger';
}

Or, if you are using a relation group, you can use the badgeColor() method:

use Filament\Resources\RelationManagers\RelationGroup;
 
RelationGroup::make('Contacts', [
// ...
])->badgeColor('danger');

Adding a tooltip to relation manager tab badges

If a badge value is defined, you can add a tooltip to it by setting the $badgeTooltip property:

protected static ?string $badgeTooltip = 'There are new posts';

Alternatively, you can override the getBadgeTooltip() method:

use Illuminate\Database\Eloquent\Model;
 
public static function getBadgeTooltip(Model $ownerRecord, string $pageClass): ?string
{
return 'There are new posts';
}

Or, if you are using a relation group, you can use the badgeTooltip() method:

use Filament\Resources\RelationManagers\RelationGroup;
 
RelationGroup::make('Contacts', [
// ...
])->badgeTooltip('There are new posts');

Sharing a resource's form and table with a relation manager

You may decide that you want a resource's form and table to be identical to a relation manager's, and subsequently want to reuse the code you previously wrote. This is easy, by calling the form() and table() methods of the resource from the relation manager:

use App\Filament\Resources\Blog\PostResource;
use Filament\Forms\Form;
use Filament\Tables\Table;
 
public function form(Form $form): Form
{
return PostResource::form($form);
}
 
public function table(Table $table): Table
{
return PostResource::table($table);
}

Hiding a shared form component on the relation manager

If you're sharing a form component from the resource with the relation manager, you may want to hide it on the relation manager. This is especially useful if you want to hide a Select field for the owner record in the relation manager, since Filament will handle this for you anyway. To do this, you may use the hiddenOn() method, passing the name of the relation manager:

use App\Filament\Resources\Blog\PostResource\RelationManagers\CommentsRelationManager;
use Filament\Forms\Components\Select;
 
Select::make('post_id')
->relationship('post', 'title')
->hiddenOn(CommentsRelationManager::class)

Hiding a shared table column on the relation manager

If you're sharing a table column from the resource with the relation manager, you may want to hide it on the relation manager. This is especially useful if you want to hide a column for the owner record in the relation manager, since this is not appropriate when the owner record is already listed above the relation manager. To do this, you may use the hiddenOn() method, passing the name of the relation manager:

use App\Filament\Resources\Blog\PostResource\RelationManagers\CommentsRelationManager;
use Filament\Tables\Columns\TextColumn;
 
TextColumn::make('post.title')
->hiddenOn(CommentsRelationManager::class)

Hiding a shared table filter on the relation manager

If you're sharing a table filter from the resource with the relation manager, you may want to hide it on the relation manager. This is especially useful if you want to hide a filter for the owner record in the relation manager, since this is not appropriate when the table is already filtered by the owner record. To do this, you may use the hiddenOn() method, passing the name of the relation manager:

use App\Filament\Resources\Blog\PostResource\RelationManagers\CommentsRelationManager;
use Filament\Tables\Filters\SelectFilter;
 
SelectFilter::make('post')
->relationship('post', 'title')
->hiddenOn(CommentsRelationManager::class)

Overriding shared configuration on the relation manager

Any configuration that you make inside the resource can be overwritten on the relation manager. For example, if you wanted to disable pagination on the relation manager's inherited table but not the resource itself:

use App\Filament\Resources\Blog\PostResource;
use Filament\Tables\Table;
 
public function table(Table $table): Table
{
return PostResource::table($table)
->paginated(false);
}

It is probably also useful to provide extra configuration on the relation manager if you wanted to add a header action to create, attach, or associate records in the relation manager:

use App\Filament\Resources\Blog\PostResource;
use Filament\Tables;
use Filament\Tables\Table;
 
public function table(Table $table): Table
{
return PostResource::table($table)
->headerActions([
Tables\Actions\CreateAction::make(),
Tables\Actions\AttachAction::make(),
]);
}

Customizing the relation manager Eloquent query

You can apply your own query constraints or model scopes that affect the entire relation manager. To do this, you can pass a function to the modifyQueryUsing() method of the table, inside which you can customize the query:

use Filament\Tables;
use Illuminate\Database\Eloquent\Builder;
 
public function table(Table $table): Table
{
return $table
->modifyQueryUsing(fn (Builder $query) => $query->where('is_active', true))
->columns([
// ...
]);
}

Customizing the relation manager title

To set the title of the relation manager, you can use the $title property on the relation manager class:

protected static ?string $title = 'Posts';

To set the title of the relation manager dynamically, you can override the getTitle() method on the relation manager class:

use Illuminate\Database\Eloquent\Model;
 
public static function getTitle(Model $ownerRecord, string $pageClass): string
{
return __('relation-managers.posts.title');
}

The title will be reflected in the heading of the table, as well as the relation manager tab if there is more than one. If you want to customize the table heading independently, you can still use the $table->heading() method:

use Filament\Tables;
 
public function table(Table $table): Table
{
return $table
->heading('Posts')
->columns([
// ...
]);
}

Customizing the relation manager record title

The relation manager uses the concept of a "record title attribute" to determine which attribute of the related model should be used to identify it. When creating a relation manager, this attribute is passed as the third argument to the make:filament-relation-manager command:

php artisan make:filament-relation-manager CategoryResource posts title

In this example, the title attribute of the Post model will be used to identify a post in the relation manager.

This is mainly used by the action classes. For instance, when you attach or associate a record, the titles will be listed in the select field. When you edit, view or delete a record, the title will be used in the header of the modal.

In some cases, you may want to concatenate multiple attributes together to form a title. You can do this by replacing the recordTitleAttribute() configuration method with recordTitle(), passing a function that transforms a model into a title:

use App\Models\Post;
use Filament\Tables\Table;
 
public function table(Table $table): Table
{
return $table
->recordTitle(fn (Post $record): string => "{$record->title} ({$record->id})")
->columns([
// ...
]);
}

If you're using recordTitle(), and you have an associate action or attach action, you will also want to specify search columns for those actions:

use Filament\Tables\Actions\AssociateAction;
use Filament\Tables\Actions\AttachAction;
 
AssociateAction::make()
->recordSelectSearchColumns(['title', 'id']);
 
AttachAction::make()
->recordSelectSearchColumns(['title', 'id'])

Relation pages

Using a ManageRelatedRecords page is an alternative to using a relation manager, if you want to keep the functionality of managing a relationship separate from editing or viewing the owner record.

This feature is ideal if you are using resource sub-navigation, as you are easily able to switch between the View or Edit page and the relation page.

To create a relation page, you should use the make:filament-page command:

php artisan make:filament-page ManageCustomerAddresses --resource=CustomerResource --type=ManageRelatedRecords

When you run this command, you will be asked a series of questions to customize the page, for example, the name of the relationship and its title attribute.

You must register this new page in your resource's getPages() method:

public static function getPages(): array
{
return [
'index' => Pages\ListCustomers::route('/'),
'create' => Pages\CreateCustomer::route('/create'),
'view' => Pages\ViewCustomer::route('/{record}'),
'edit' => Pages\EditCustomer::route('/{record}/edit'),
'addresses' => Pages\ManageCustomerAddresses::route('/{record}/addresses'),
];
}

When using a relation page, you do not need to generate a relation manager with make:filament-relation-manager, and you do not need to register it in the getRelations() method of the resource.

Now, you can customize the page in exactly the same way as a relation manager, with the same table() and form().

Adding relation pages to resource sub-navigation

If you're using resource sub-navigation, you can register this page as normal in getRecordSubNavigation() of the resource:

use App\Filament\Resources\CustomerResource\Pages;
use Filament\Resources\Pages\Page;
 
public static function getRecordSubNavigation(Page $page): array
{
return $page->generateNavigationItems([
// ...
Pages\ManageCustomerAddresses::class,
]);
}

Passing properties to relation managers

When registering a relation manager in a resource, you can use the make() method to pass an array of Livewire properties to it:

use App\Filament\Resources\Blog\PostResource\RelationManagers\CommentsRelationManager;
 
public static function getRelations(): array
{
return [
CommentsRelationManager::make([
'status' => 'approved',
]),
];
}

This array of properties gets mapped to public Livewire properties on the relation manager class:

use Filament\Resources\RelationManagers\RelationManager;
 
class CommentsRelationManager extends RelationManager
{
public string $status;
 
// ...
}

Now, you can access the status in the relation manager class using $this->status.

Disabling lazy loading

By default, relation managers are lazy-loaded. This means that they will only be loaded when they are visible on the page.

To disable this behavior, you may override the $isLazy property on the relation manager class:

protected static bool $isLazy = false;
Edit on GitHub

Still need help? Join our Discord community or open a GitHub discussion