njxqlus/filament-relation-manager-component
Installation:
composer require njxqlus/filament-relation-manager-component
Publish views (optional, for customization):
php artisan vendor:publish --tag="filament-relation-manager-component-views"
First Use Case:
Integrate into a Filament resource's form() or table() method. Example for a Post resource managing Comments:
use Njxqlus\Filament\Components\Forms\RelationManager;
public static function form(Schema $schema): Schema {
return $schema->schema([
RelationManager::make('comments')
->relationship('comments') // Define the relationship
->manager(CommentsRelationManager::class) // Custom manager class
->lazy(false), // Load immediately (not lazy-loaded)
]);
}
Key Files to Review:
app/Filament/Resources/[ResourceName]/Pages/EditPost.php (for form integration).app/Filament/RelationManagers/CommentsRelationManager.php (custom manager logic).vendor/njxqlus/filament-relation-manager-component/src/Components/ (core components).Basic Integration:
RelationManager::make() in form() or table() methods.->relationship('comments')).RelationManager class (extends Filament\Forms\Components\RelationManager).Tabbed Layouts: Group multiple relation managers in tabs for organized UX:
Schemas\Components\Tabs::make()->tabs([
Schemas\Components\Tabs\Tab::make('Comments')->schema([
RelationManager::make()->manager(CommentsRelationManager::class),
]),
Schemas\Components\Tabs\Tab::make('Tags')->schema([
RelationManager::make()->manager(TagsRelationManager::class),
]),
]);
Custom Managers:
Extend Filament\Forms\Components\RelationManager to override default behavior:
namespace App\Filament\RelationManagers;
use Filament\Forms;
use Filament\Forms\Form;
use Filament\Tables;
class CommentsRelationManager extends \Filament\Forms\Components\RelationManager {
protected static ?string $model = Comment::class;
public function form(Form $form): Form {
return $form
->schema([
Forms\Components\TextInput::make('body')->required(),
Forms\Components\Select::make('status')->options(['draft', 'published']),
]);
}
}
Infolist Integration:
Display read-only relations in infolist():
public static function infolist(Schema $schema): Schema {
return $schema->schema([
RelationManager::make('comments')
->relationship('comments')
->manager(CommentsRelationManager::class)
->lazy(false),
]);
}
Modal/Slideover Support:
Use ->modal() or ->slideover() for inline editing:
RelationManager::make()
->manager(CommentsRelationManager::class)
->modal()
->slideover();
Dynamic Relationships: Use closures to define relationships dynamically:
RelationManager::make()
->relationship(fn ($record) => $record->currentTeam()->comments())
Conditional Rendering: Show/hide relation managers based on logic:
RelationManager::make()
->manager(CommentsRelationManager::class)
->visible(fn ($record) => $record->isApproved())
Bulk Actions: Extend the manager to support bulk operations:
class CommentsRelationManager extends \Filament\Forms\Components\RelationManager {
public function table(Tables\Table $table): Tables\Table {
return $table
->columns([
Tables\Columns\TextColumn::make('body'),
])
->actions([
Tables\Actions\DeleteAction::make(),
Tables\Actions\EditAction::make(),
])
->bulkActions([
Tables\Actions\BulkAction::make('approve')
->action(fn (Collection $records) => $records->update(['status' => 'approved']))
]);
}
}
Lazy Loading:
lazy(true)). Set lazy(false) for immediate rendering (e.g., in tabs).lazy() to avoid unexpected delays.Owner Record Assignment:
ownerRecord isn’t properly passed (e.g., in modals/slideovers).getOwnerRecord() method is implemented:
public static function getOwnerRecord(): ?Model {
return parent::getOwnerRecord() ?? request()->filamentResourceRecord;
}
Filament Version Mismatches:
composer.json for required versions.\Filament\Forms\Components\RelationManager for v3, \Filament\Forms\Components\RelationManager for v4+).Published Views:
resources/views/vendor/filament-relation-manager-component/.php artisan vendor:publish --tag="filament-relation-manager-component-views" and modify the published files.Performance with Large Datasets:
->query() to scope relations:
RelationManager::make()
->relationship('comments')
->query(fn ($query) => $query->where('status', 'published'))
Check the Owner Record:
Add a dd() in the manager’s getOwnerRecord() to verify the parent model is passed correctly.
Log Queries: Enable Laravel’s query logging to debug relation queries:
DB::enableQueryLog();
// ... perform action ...
dd(DB::getQueryLog());
Inspect the Schema:
Use Schema::make()->toHtml() to debug the rendered schema structure.
Custom Table/Form Components: Override the table or form in the manager class:
public function table(Tables\Table $table): Tables\Table {
return $table->columns([...]);
}
Event Hooks:
Listen to Filament’s events (e.g., RelationManagerSaved) for post-save logic:
event(new RelationManagerSaved($this, $record));
API Integration:
Extend the manager to support API-only workflows by implementing getApiResource():
public function getApiResource(): ?string {
return \App\Filament\Resources\CommentResource::class;
}
Localization: Override labels and messages in the manager:
public static ?string $label = 'Customer Reviews';
public static ?string $pluralLabel = 'Customer Reviews';
Reuse Managers Across Resources: Create a base manager class and extend it for shared logic:
class BaseRelationManager extends \Filament\Forms\Components\RelationManager {
public function getTitle(): string {
return $this->getOwnerRecord()->name . ' Relations';
}
}
Use hasManyThrough:
Support complex relationships like hasManyThrough:
RelationManager::make()
->relationship('posts')
->manager(PostsRelationManager::class)
->query(fn ($query) => $query->whereHas('author', fn ($q) => $q->where('user_id', $this->getOwnerRecord()->id)))
Testing: Test relation managers with Filament’s testing helpers:
$this->actingAsUser($user)
->get('/admin/resources/posts/1/edit')
->assertSee('Relation Manager Title');
How can I help you explore Laravel packages today?