asosick/filament-layout-manager
Installation:
composer require asosick/filament-layout-manager
Publish the config file:
php artisan vendor:publish --provider="Asosick\FilamentLayoutManager\FilamentLayoutManagerServiceProvider" --tag="config"
First Use Case: Generate a new page using Artisan:
php artisan make:layout-manager-page dashboard
This creates a new page class in app/Filament/Pages/DashboardPage.php.
Register the Page:
Add the page to your Filament admin panel configuration (e.g., app/Providers/Filament/AdminPanelProvider.php):
public function panel(Panel $panel): Panel
{
return $panel
->pages([
// ...
\App\Filament\Pages\DashboardPage::class,
]);
}
Access the Page: Visit the page in your Filament admin panel to see the interactive layout manager UI.
DashboardPage as a base for customizable dashboards.$widgets property:
public array $widgets = [
\App\Filament\Widgets\StatsOverviewWidget::class,
\App\Filament\Widgets\RecentActivityWidget::class,
];
LayoutManagerPage for custom pages:
use Asosick\FilamentLayoutManager\Pages\LayoutManagerPage;
class CustomPage extends LayoutManagerPage
{
protected static ?string $navigationIcon = 'heroicon-o-document-duplicate';
protected static string $view = 'filament-layout-manager::pages.layout-manager';
}
$widgetData to pass dynamic data to widgets:
public function getWidgetData(): array
{
return [
'stats' => Stats::query()->latest()->limit(5)->get(),
];
}
$this->widgetData['stats'].filament-layout-manager:install migration):
php artisan migrate
use Filament\Pages\Page;
class Dashboard extends Page
{
public function mount(): void
{
LayoutManager::setPage($this);
}
public function render()
{
return view('filament-layout-manager::pages.layout-manager');
}
}
Widget Development:
Ensure widgets extend Filament\Widgets\Widget and are registered in $widgets.
Example:
class StatsOverviewWidget extends Widget
{
protected static string $view = 'filament.widgets.stats-overview';
}
Customizing Layout UI: Override the default layout manager view by publishing assets:
php artisan vendor:publish --provider="Asosick\FilamentLayoutManager\FilamentLayoutManagerServiceProvider" --tag="views"
Then modify resources/views/vendor/filament-layout-manager/pages/layout-manager.blade.php.
Conditional Widgets:
Use closures in $widgets to conditionally include widgets:
public array $widgets = [
fn() => auth()->user()->can('view_stats') ? \App\Filament\Widgets\StatsWidget::class : null,
];
Widget Registration Issues:
\App\Filament\Widgets\...).$widgets property of the page class.Layout Not Saving:
layouts table exists (run migrations if needed).LayoutManager facade is properly initialized in your page:
public static function getLayoutManager(): LayoutManager
{
return app(LayoutManager::class);
}
Data Not Passing to Widgets:
getWidgetData() is defined and returns the expected array.$widgetData['stats'] vs. $widgetData['stat']).Conflicting CSS/JS:
php artisan filament:cache:clear
Default Layout Behavior:
default_layout to null in config/filament-layout-manager.php:
'default_layout' => null,
Customizing Selection Options:
getWidgetOptions() method in your page class:
public function getWidgetOptions(): array
{
return [
'stats' => 'Statistics',
'activity' => 'Recent Activity',
];
}
Extending LayoutManager:
LayoutManager class:
use Asosick\FilamentLayoutManager\LayoutManager as BaseLayoutManager;
class CustomLayoutManager extends BaseLayoutManager
{
public function saveLayout(array $layout): void
{
// Custom logic before saving
parent::saveLayout($layout);
}
}
AppServiceProvider:
public function register(): void
{
$this->app->bind(
\Asosick\FilamentLayoutManager\LayoutManager::class,
\App\Services\CustomLayoutManager::class
);
}
Adding Header Actions:
Use the $headerActions property to add buttons or dropdowns:
public array $headerActions = [
\Asosick\FilamentLayoutManager\Actions\ResetLayoutAction::class,
\Asosick\FilamentLayoutManager\Actions\SaveLayoutAction::class,
];
Child Component Data Stores:
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\Field;
public function form(FieldsForm $form): FieldsForm
{
return $form->schema([
Field::make('shared_data')
->label('Shared Data')
->columnSpanFull(),
Action::make('saveData')
->action(fn() => $this->saveSharedData()),
]);
}
public function saveSharedData(): void
{
$this->callHook('saveSharedData');
}
$this->callHook('getSharedData').Custom Storage Backends:
LayoutRepository:
use Asosick\FilamentLayoutManager\Repositories\LayoutRepositoryInterface;
class CustomLayoutRepository implements LayoutRepositoryInterface
{
public function save(array $layout, string $pageClass): void
{
// Custom logic (e.g., save to Redis, S3, etc.)
}
public function get(string $pageClass): ?array
{
// Custom logic
}
}
AppServiceProvider:
$this->app->bind(
LayoutRepositoryInterface::class,
CustomLayoutRepository::class
);
How can I help you explore Laravel packages today?