Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Modal Relation Managers Laravel Package

guava/filament-modal-relation-managers

Open any relation manager inside a modal with a Filament action, from table rows, schema entries, or page headers, no edit page needed. Supports Filament 3, 4, and 5.

View on GitHub
Deep Wiki
Context7

Getting Started

Install and wire the theme (do this first, it is the only real setup cost).

composer require guava/filament-modal-relation-managers

Then, in your panel's custom theme resources/css/filament/admin/theme.css, add the @source line so Tailwind picks up the package's modal markup:

@source '../../../../vendor/guava/filament-modal-relation-managers/resources/**/*';

If you don't already have a custom theme, create one (php artisan filament:theme on 4.x/5.x), register it via ->viteTheme('resources/css/filament/admin/theme.css') on the panel, and rebuild. Skipping this step is the #1 cause of "the modal opens but looks broken."

Pick the version that matches your Filament major. They are hard-pinned, not ranges:

Filament Plugin
3.x 1.x
4.x 2.x
5.x 3.x

First use case. Take an existing relation manager you already have on a resource's edit page (app/Filament/Resources/LessonResource/RelationManagers/StudentsRelationManager.php) and surface it on the parent table row, so a user can inspect/edit related records without leaving the list:

use Guava\FilamentModalRelationManagers\Actions\RelationManagerAction;

return $table
    ->recordActions([
        RelationManagerAction::make('students')
            ->label('Students')
            ->relationManager(StudentsRelationManager::class),
    ]);

Where to look first. The action class Guava\FilamentModalRelationManagers\Actions\RelationManagerAction — read its setUp()/getRelationManager() and the modal-configuration methods. It extends the standard Filament action, so everything you know about ->modalHeading(), ->modalWidth(), ->modalSubmitAction() etc. applies. After that, the vendor resources/views directory tells you exactly what markup is rendered into the modal (and what your @source line is compiling).

Implementation Patterns

The three mount points. The action is context-agnostic; what changes is which action array you push it into and what the surrounding record is.

  • Table row action — the bread-and-butter case. ->recordActions([...]) on the table of the parent resource. The row's model becomes the owner record the relation manager is bound to.
  • Schema component — inside a form/infolist ->schema([...]), e.g. a Section on the edit page, or a custom action block. Use this when you want the relation accessible alongside the record's fields rather than under a relation-manager tab.
  • Page header action — ->headerActions([...]) on a ListRecords/ViewRecord page, typically for a global-ish relation on the page's record.

Pass the class, not an instance. ->relationManager(LessonRelationManager::class) — the package instantiates and wires the owner record itself. Don't try to new it up.

Compact style for dense tables. If the action sits in a busy row with several other actions, use the compact variant so it renders as an icon-only button and doesn't bloat the row. Combine with ->icon(), ->tooltip(), and a ->label() that still reads well in the accessible name.

Reuse, don't duplicate. The whole point is that you keep authoring relation managers normally and gain a second mount point. A useful pattern: keep the relation manager registered on the edit page's getRelations() and add the action to the list table. Same class, same table(), same form() — no divergence in behaviour, no second source of truth for columns.

Gate it like any other action. Because it's a plain Filament action, all the usual authorization applies:

RelationManagerAction::make('students')
    ->relationManager(StudentsRelationManager::class)
    ->visible(fn (Lesson $record) => auth()->user()->can('view', $record))
    ->modalWidth('7xl'),

The relation manager's own canViewForRecord() still runs — so policy checks written for the edit page carry over unchanged. Verify this explicitly the first time you add one.

Drill-down navigation. In list views of nested resources, use the modal action instead of ->url() to a full edit page. Users keep their filters, search state, and pagination — this is the biggest day-to-day UX win and the reason to reach for the package at all.

Modal sizing per relation. Wide tables (many columns) need ->modalWidth('7xl') or Width::Full. Narrow relations look better at default. Set this at the action, not globally.

Gotchas and Tips

The silent CSS failure is the real risk. Styling comes from vendor files compiled into your theme. A stale build, a missing @source line, or a deploy that ships PHP before assets produces a visually broken modal with zero runtime errors and nothing in the logs. Mitigations: commit the built asset pipeline into CI, run npm run build as an explicit deploy step before the PHP release, and smoke-test the modal on staging after every Filament/theme upgrade. Unit tests will never catch this.

Version lock-step with Filament. No plugin major spans two Filament majors. A Filament 4 → 5 upgrade forces a plugin 2.x → 3.x bump in the same change window. Put this on the upgrade checklist rather than discovering it via a composer conflict mid-sprint.

The CanBeEmbeddedInModals trait is gone (1.3.0+). Older tutorials and Stack Overflow answers may tell you to add it to your relation manager. Don't — 1.3.0 removed the requirement. If you're on 1.x pre-1.3, that's a breaking-change boundary to plan for.

pageClass fidelity. The changelog shows repeated iteration here (1.3.0, 1.4.0 — "pass correct pageClass to relation manager action"). Anything your relation manager does that inspects the owning page/record context (custom getOwnerRecord(), redirects, $this->getPageClass()) is the historical weak spot. If a relation manager behaves differently in the modal than on the edit page, test in isolation on the exact plugin version you're pinning — and don't float the constraint.

Debugging a modal that won't render. Order of checks: (1) does the relation manager work on the record's edit page? If no, it's your class, not the package. (2) Did the theme rebuild after install? (3) Is the owner record actually resolvable from that mount point — e.g. a page header action on ListRecords may not have a record bound, so the action won't have an owner. (4) php artisan filament:assets / view:clear after any vendor change.

Nested modals. Opening a relation manager that itself contains row actions opening modals can stack. Keep nesting to one level; if a relation manager's own actions open a modal, prefer a full page or a slide-over for the deeper level.

Extension points. The action is a normal Filament action, so ->modalHeading(), ->modalDescription(), ->modalIcon(), ->modalWidth(), ->modalSubmitAction(false) and the ->action() closure are all fair game. For behaviour that repeats across many relations, write a small factory:

RelationManagerAction::make('related')
    ->relationManager($manager)
    ->modalWidth('7xl')
    ->modalSubmitAction(false)
    ->modalCancelActionLabel('Close');

Testing. composer test in the package isn't your test suite. For your app, cover it with a Livewire test that calls the action and asserts the relation manager's table renders and respects the policy — that catches authorization and owner-record wiring regressions, which are the two things a CSS-blind unit test can still catch.

Don't use it to hide broken IA. If users constantly need to reach a related record's own edit page, the modal is a detour. The package is for editing relations, not for replacing resource navigation. Keep ->url() on the related resource's name column and let the modal handle relation CRUD.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings