solution-forest/filament-field-group
Group and organize Filament form fields with reusable field groups: create collapsible sections, tabs, and custom layouts to make large forms cleaner, easier to navigate, and more maintainable. Supports Filament v3–v5 (matching plugin versions).
## Getting Started
### First Steps
1. **Installation**:
```bash
composer require solution-forest/filament-field-group
php artisan filament-field-group:install
Register the plugin in your PanelProvider:
use SolutionForest\FilamentFieldGroup\FilamentFieldGroupPlugin;
public function panel(Panel $panel): Panel {
return $panel->plugin(FilamentFieldGroupPlugin::make()->enablePlugin());
}
Enable the Plugin:
'enabled' => true in config/filament-field-group.php or use ->enablePlugin() in your PanelProvider.First Use Case:
Text, Email, Toggle) to the group.use SolutionForest\FilamentFieldGroup\Facades\FilamentFieldGroup;
public static function form(Form $form): Form {
return $form->schema([
FilamentFieldGroup::findFieldGroup('user_profile'),
]);
}
Define Groups:
name, email, and phone under "Contact Details."Reuse Groups in Forms:
$form->schema([
FilamentFieldGroup::findFieldGroup('contact_details'),
FilamentFieldGroup::findFieldGroup('billing_info'),
]);
Conditional Rendering:
statePath config to dynamically show/hide groups based on form state:
FilamentFieldGroup::findFieldGroup('advanced_options')
->statePath('show_advanced')
Nested Groups:
Custom Field Types:
RichText field):
class RichTextField extends FieldTypeBaseConfig {
public function getFormSchema(): array {
return [
RichEditor::make('content')->columnSpanFull(),
];
}
}
FilamentFieldGroupPlugin::make()->fieldTypeConfigs([RichTextField::class]).Dynamic Group Loading:
if (auth()->user()->can('edit_advanced')) {
$form->schema([FilamentFieldGroup::findFieldGroup('admin_settings')]);
}
State-Dependent Logic:
configureFieldTypeConfigFormUsing to add dynamic options:
FilamentFieldGroup::configureFieldTypeConfigFormUsing(
Text::class,
fn ($field, $schema) => array_merge($schema, [
Toggle::make('required')->default(false),
])
);
Resource Overrides:
$panel->plugin(FilamentFieldGroupPlugin::make()->resources([
CustomFieldGroupResource::class,
], override: true));
Field Group Not Found:
'enabled' => true.dd(FilamentFieldGroup::findFieldGroup('group_name')); // Returns null if not found.
State Path Mismatches:
statePath values in groups match the form’s state array keys.statePath('is_active') is set, ensure the form tracks is_active.Caching Issues:
php artisan filament:cache-reset
Migration Conflicts:
config/filament-field-group.php:
'table_names' => [
'fields' => 'custom_advanced_fields',
'field_groups' => 'custom_advanced_field_groups',
],
Reusable Configs:
// config/filament-field-groups.php
return [
'user_profile' => 'user_profile_group',
'billing' => 'billing_group',
];
Usage:
FilamentFieldGroup::findFieldGroup(config('filament-field-groups.user_profile'));
Validation Rules:
class RequiredMixin {
public function addRequiredRule() {
return fn () => ['required'];
}
}
Text::mixin(new RequiredMixin());
Performance:
FilamentFieldGroup::findFieldGroup('group_name')->eagerLoadFields();
Testing:
FilamentFieldGroup::shouldReceive('findFieldGroup')
->once()
->andReturn(FakeFieldGroup::new());
Debugging:
dd(FilamentFieldGroup::findFieldGroup('group_name')->getFormSchema());
Localization:
php artisan vendor:publish --tag="filament-field-group-translations"
Filament 5+ Compatibility:
FilamentFieldGroup::make() (v3+) for newer Filament versions:
FilamentFieldGroup::make()->schema([...])->statePath('dynamic_key');
---
How can I help you explore Laravel packages today?