yousefaman/filament-modal-repeater
Installation:
composer require yousefaman/filament-modal-repeater
php artisan modal-repeater:install
Register the plugin in your PanelProvider (optional but recommended):
->plugin(ModalRepeaterPlugin::make())
First Use Case:
Add a ModalRepeater to a Filament form (e.g., Create or Edit resource):
use YousefAman\ModalRepeater\ModalRepeater;
ModalRepeater::make('items')
->tableColumns([
Column::make('name')->label('Name'),
Column::make('price')->label('Price'),
])
->modalHeading('Edit Item')
->modalSubmitAction('Update')
->modalCancelAction('Cancel')
->columns([
TextInput::make('name')->required(),
TextInput::make('price')->numeric(),
]);
art/demo.jpeg in the repo for visual guidance.Usage section in the README for basic syntax.src/ModalRepeater.php and src/Column.php for customization hooks.Define Repeater Structure:
Use ModalRepeater::make('key') to initialize, where 'key' maps to your model’s array field (e.g., $model->items).
ModalRepeater::make('features')
->tableColumns([...]) // Display columns in the table view
->columns([...]) // Form fields in the modal
Modal Configuration: Customize the modal with:
modalHeading(), modalSubmitAction(), modalCancelAction().modalWidth() (e.g., '500px' for fixed width).modalMaxHeight() (e.g., '80vh' for scrollable content).Dynamic Columns:
Use Column::make('field')->label('Label') for table columns. Add actions like:
Column::make('status')
->toggle()
->label('Active')
Form Fields:
Nest standard Filament fields (e.g., TextInput, Select) inside columns():
->columns([
TextInput::make('description')->rows(3),
Select::make('category')->options(['A', 'B']),
])
Data Binding:
Ensure your model uses protected $casts = ['items' => 'array'] for array fields.
Resource Integration:
Attach to a Filament Form or Table via getFormSchema() or getTableColumns():
public static function form(Form $form): Form
{
return $form->schema([
ModalRepeater::make('items')->...,
]);
}
Validation:
Use Filament’s validation rules within columns():
TextInput::make('email')->email()->required()
Conditional Logic:
Leverage Filament’s visible() or required() on nested fields:
TextInput::make('notes')->visible(fn ($record) => $record->is_active)
Livewire Events:
Listen for repeater changes via ModalRepeater's events (e.g., saved, deleted):
protected $listeners = ['modalRepeaterSaved' => 'handleRepeaterSave'];
Key Mismatch:
ModalRepeater::make('key') matches the array key in your model’s $casts.protected $casts = ['items' => 'array'] in your model.Modal Persistence:
modalSubmitAction() isn’t set.modalSubmitAction('Save') or similar.Nested Repeaters:
ModalRepeater inside another ModalRepeater (untested/unsupported).CSRF Issues:
@csrf in layouts.resources/views/layouts/filament-app.blade.php.Performance:
modalMaxHeight() to limit modal size.->paginate(10).Console Logs: Enable Filament’s debug mode to log repeater interactions:
FILAMENT_DEBUG=true
Data Dumping:
Use dd($this->data) in your model’s save() method to inspect repeater payloads.
Event Listeners:
Debug repeater events by listening to ModalRepeaterSaved:
public function handleRepeaterSave(array $data)
{
logger()->info('Repeater data:', $data);
}
Custom Modal Content: Override the modal template by publishing views:
php artisan vendor:publish --tag=modal-repeater-views
Then modify resources/views/vendor/modal-repeater/modal.blade.php.
Dynamic Columns: Use closures for dynamic column generation:
->tableColumns([
Column::make('created_at')
->dateTime()
->label('Added')
->sortable(),
])
API Integration:
Extend the repeater to work with API resources by overriding getState():
ModalRepeater::make('metadata')
->state(fn () => $this->metadata ?? [])
->mutateStateUsing(fn (array $state) => $state)
Localization:
Translate labels/actions via Filament’s __() helper:
->modalHeading(__('Edit Item'))
->modalSubmitAction(__('Save Changes'))
How can I help you explore Laravel packages today?