rodrigofs / filament-masterdetail
Filament plugin designed specifically for managing Laravel HasMany relationships without relying on Filament's default repeater field, using instead a dedicated modal and table-based form interface.
Fund package maintenance!
rodrigofs
Requires
- php: ^8.1
- filament/filament: ^3.2
- spatie/laravel-package-tools: ^1.92
Requires (Dev)
- filament/support: ^3.2
- larastan/larastan: ^v3.2
- laravel/pint: ^v1.21
- nunomaduro/collision: ^7.8|^v8.7
- orchestra/testbench: ^8.8|^9.0|^10.0
- pestphp/pest: ^v3.7.2
- pestphp/pest-plugin-arch: ^3.0
- pestphp/pest-plugin-laravel: v3.1.0
- pestphp/pest-plugin-livewire: v3.0.0
This package is auto-updated.
Last update: 2025-04-21 11:51:30 UTC
README
Overview
Filament Master Detail is a dynamic management plugin Form Component for HasMany (1,n) relationships in FilamentPHP. It allows you to add and remove related records directly within the parent form, without the need to save the parent record first. Ideal for fast and fluid data entry scenarios.
Table of Contents
- Installation
- Basic Usage
- Common Use Cases
- Additional Features
- Full Example
- Editing Behavior
- FAQ
- Screenshots
- Changelog
- Contributing
- Security
- License
Installation
Requirements
- PHP >= 8.1
- Laravel >= 10
- Filament >= 3.x
Installation Steps
composer require rodrigofs/filament-masterdetail
Basic Usage
Important: When using the table(...) method, it is not compatible with Filament's TextColumn or other default columns. You must exclusively use the DataColumn provided by this package.
Example
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; use Rodrigofs\FilamentMasterDetail\Tables\Columns\DataColumn; MasterDetail::make('items') ->relationship('items') ->schema([ TextInput::make('name')->required(), TextInput::make('description'), ]) ->table([ DataColumn::make('name'), DataColumn::make('description'), ]);
Define the HasMany relationship in the parent model:
public function items(): HasMany { return $this->hasMany(Item::class); }
Common Use Cases
Order Creation with Items
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; use Rodrigofs\FilamentMasterDetail\Tables\Columns\DataColumn; MasterDetail::make('items') ->relationship() ->schema([ Select::make('shop_product_id') ->label('Product') ->options(Product::query()->pluck('name', 'id')) ->required() ->reactive() ->afterStateUpdated(fn ($state, Set $set) => $set('price', Product::find($state)?->price ?? 0)) ->distinct() ->disableOptionsWhenSelectedInSiblingRepeaterItems() ->columnSpan(['md' => 5]) ->searchable(), TextInput::make('quantity') ->label('Quantity') ->numeric() ->default(1) ->required() ->columnSpan(['md' => 2]), TextInput::make('price') ->label('Unit Price') ->numeric() ->disabled() ->dehydrated() ->required() ->columnSpan(['md' => 3]), ]) ->unique('shop_product_id') ->table([ DataColumn::make('product.name') ->relationship() ->label('Product'), DataColumn::make('quantity') ->label('Quantity'), DataColumn::make('price') ->label('Unit Price'), DataColumn::make('total') ->formatStateUsing(fn ($rowLoop) => $rowLoop->price * $rowLoop->quantity) ->label('Total'), ]);
Additional Features
Behavior & Customization
You can customize the behavior of the component and the appearance and behavior of the modal used to add, delete, and edit related records:
Disable Actions
Disable the default Add, Delete, and Edit actions on the component:
use Rodrigofs\FilamentMasterDetail\Components\MasterDetail; // Disable actions statically MasterDetail::make('items') ->addable(false) ->editable(false) ->removable(false) ->schema([ // Form fields ]); // Disable actions conditionally using closures MasterDetail::make('items') ->addable(fn (): bool => /* condition based on $record, $get, $state, $operation and more... */ false) ->editable(fn (...): bool => /* condition based on $record, $get, $state, $operation and more... */ false) ->removable(fn (...): bool => /* condition based on $record, $get, $state, $operation and more... */ false) ->schema([ // Form fields ]);
Slideover Mode
Display the form inside a Slideover instead of a traditional modal:
use Rodrigofs\FilamentMasterDetail\Components\MasterDetail; MasterDetail::make('items') ->slideover() ->schema([ // Form fields ]);
Set Custom Labels
Define the labels for modal actions and headings:
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; MasterDetail::make('items') ->addActionLabel('Add Product') ->modalHeading('Add Product') ->modalDescription('Include a new product in this order.') ->modalSubmitActionLabel('Add') ->modalSubmitEditActionLabel('Edit') ->modalCancelActionLabel('Cancel');
Set Modal Icon and Width
Customize the modal icon and size:
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; MasterDetail::make('items') ->modalIcon('heroicon-o-plus') ->modalWidth('lg');
Keep Modal Open After Adding
Prevent the modal from closing automatically after adding a record:
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; MasterDetail::make('items') ->modalPersistent();
Customize Table Heading
Set a custom heading for the related records table:
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; MasterDetail::make('items') ->heading('Order Items');
Preserve Field Values
Prevent specific fields from being cleared after adding a record:
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; MasterDetail::make('items') ->formExceptClear(['product_id']);
Manipulate Data Before Adding
Allow data manipulation before the record is added to the table:
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; MasterDetail::make('items') ->beforeAddActionExecute(fn ($state, $set) => $set('product_id', $state));
Add Header Actions
Define custom actions in the header of the MasterDetail component:
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; MasterDetail::make('items') ->headerActions([ Action::make('reset') ->modalHeading('Are you sure?') ->modalDescription('All existing items will be removed from the order.') ->requiresConfirmation() ->color('danger') ->action(fn (Forms\Set $set) => $set('items', [])), ]);
There are many additional features available—more than can be covered at once. While I will continue to document them, I encourage you to freely explore all possibilities. Don’t hesitate to open an issue if you encounter any problems or have suggestions.
Full Example
use Rodrigofs\FilamentMasterDetail\Forms\Components\MasterDetail; MasterDetail::make('items') ->relationship() ->schema([ Select::make('product_id') ->label('Product') ->options(Product::query()->pluck('name', 'id')) ->required(), TextInput::make('quantity') ->numeric() ->required(), ]) ->table([ DataColumn::make('product.name') ->relationship() ->label('Product'), DataColumn::make('quantity') ->label('Quantity'), ]) ->addActionLabel('Add Product') ->modalHeading('Add Product') ->modalDescription('Include a new product in this order.') ->modalIcon('heroicon-o-plus') ->modalWidth('lg') ->modalSubmitActionLabel('Add') ->modalCancelActionLabel('Cancel') ->heading('Order Items') ->formExceptClear(['product_id']) ->beforeAddActionExecute(fn ($state, $set) => $set('product_id', $state)) ->headerActions([ Action::make('reset') ->modalHeading('Are you sure?') ->modalDescription('All existing items will be removed from the order.') ->requiresConfirmation() ->color('danger') ->action(fn (Forms\Set $set) => $set('items', [])), ]) ->slideOver();
Editing Behavior
The editing feature works for related records defined via the relationship() method on the component.
Important: This feature does not support custom statePath-based implementations that do not use the relationship() method. Relationship-based binding is required for the edit action to resolve the model instance correctly.
FAQ
-
Do I need to save the parent record before adding related records? No. MasterDetail allows adding and removing related records before persisting the parent model.
-
Does it support other relationship types besides HasMany? Currently, only HasMany relationships are supported.
-
Is there support for editing related records?
No. Only adding and removing records is supported at the moment.Yes. You can edit related records through an edit action.
Screenshots
Table View
Add New Item in Modal
Edit Item in Modal
Remove Item with Confirmation
Show Slideover Mode
Video Demo
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security Vulnerabilities
Please review our security policy on how to report security vulnerabilities.
Credits
License
The MIT License (MIT). Please see License File for more information.