Installation
composer require vodafoneziggo/filament-multi-widget
Update config/filament.php to include the package service provider:
'widgets' => [
'widgets' => [
\VodafoneZiggoNL\FilamentMultiWidget\Widgets\MultiWidget::class,
],
],
First Use Case
Register a MultiWidget in your Filament admin panel:
use VodafoneZiggoNL\FilamentMultiWidget\Widgets\MultiWidget;
public static function getWidgets(): array
{
return [
MultiWidget::make()
->columns(2) // Adjust columns as needed
->widgets([
\App\Filament\Widgets\StatsOverviewWidget::class,
\App\Filament\Widgets\UserActivityWidget::class,
]),
];
}
Key Files to Review
app/Providers/FilamentServiceProvider.php (for widget registration)resources/views/vendor/filament/widgets/multi-widget.blade.php (customization)config/filament.php (package configuration)Dynamic Widget Loading Fetch widgets from a database or API and render them dynamically:
MultiWidget::make()
->widgets(
WidgetRegistry::get()->filter(fn ($widget) => $widget->isVisible())
)
->canCollapse()
Conditional Rendering Use Filament’s built-in logic to show/hide widgets based on user roles:
MultiWidget::make()
->widgets([
AdminWidget::class,
UserWidget::class,
])
->canCollapse()
->visible(fn () => auth()->user()->can('view-dashboard'))
Responsive Layouts Adjust columns for different screen sizes:
MultiWidget::make()
->columns([
'sm' => 1,
'md' => 2,
'lg' => 3,
])
->widgets([...])
Nested MultiWidgets
Embed a MultiWidget inside another widget for hierarchical layouts:
class DashboardWidget extends Widget
{
public function build()
{
$this->widget(MultiWidget::make()
->columns(1)
->widgets([...])
);
}
}
Filament Widget Registry
Leverage Filament’s WidgetRegistry to discover and register widgets programmatically:
use Filament\Widgets\WidgetRegistry;
WidgetRegistry::register(
MultiWidget::make()
->columns(3)
->widgets(WidgetRegistry::get()->all())
);
Custom Styling
Override the default Blade template in resources/views/vendor/filament/widgets/multi-widget.blade.php:
<div class="grid grid-cols-{{ $columns }} gap-4">
@foreach($widgets as $widget)
<div class="filament-multi-widget-item">
{{ $widget }}
</div>
@endforeach
</div>
Livewire Integration
Use Livewire components as widgets within MultiWidget:
MultiWidget::make()
->widgets([
LivewireWidget::class,
StaticWidget::class,
])
Widget Initialization Order
Ensure all widgets are properly registered before the MultiWidget is rendered. Use service providers or boot methods to guarantee order:
public function boot()
{
WidgetRegistry::register(MultiWidget::make()->widgets([...]));
}
Caching Issues If widgets rely on cached data (e.g., Eloquent models), clear the cache after updates:
php artisan cache:clear
php artisan view:clear
Column Calculation
Misconfigured columns can cause layout breaks. Test with:
->columns(2) // Default for 2-column layout
->columns(['sm' => 1, 'md' => 2, 'lg' => 3]) // Responsive
Widget Dependencies
If a widget fails to load (e.g., missing dependencies), the entire MultiWidget may break. Use try-catch blocks:
try {
$widget = app(YourWidget::class);
} catch (\Throwable $e) {
Log::error("Widget load failed: " . $e->getMessage());
continue;
}
Inspect Rendered HTML Use browser dev tools to verify widget rendering. Check for missing classes or styles:
<div class="filament-multi-widget-item"> <!-- Ensure this wraps each widget -->
Log Widget Registration Debug widget registration with:
WidgetRegistry::get()->each(function ($widget) {
Log::debug("Registered widget: " . get_class($widget));
});
Check for Deprecated Methods The package may have evolved since its last release. Refer to the new repository for updates.
Custom Widget Classes
Extend the base MultiWidget class to add functionality:
class CustomMultiWidget extends MultiWidget
{
public function customize()
{
$this->header("Custom Header");
$this->extraAttribute('data-custom', 'value');
}
}
Dynamic Widgets via API Fetch widgets from an external API and render them dynamically:
$apiWidgets = Http::get('https://api.example.com/widgets')->json();
MultiWidget::make()->widgets(array_map(fn ($widget) => $widget['class'], $apiWidgets));
Event Listeners
Listen for widget events (e.g., WidgetRendered) to modify behavior:
event(new WidgetRendered($widget));
Localization
Override default strings in config/filament.php:
'widgets' => [
'multi_widget' => [
'collapse_label' => 'Collapse All',
'expand_label' => 'Expand All',
],
],
Default Column Count
If columns() is omitted, the package defaults to 1. Explicitly set it to avoid surprises:
->columns(2) // Always specify
Widget Visibility
Use visible() or can() methods to control widget visibility dynamically:
->widgets([
WidgetA::class,
WidgetB::class->visible(fn () => auth()->check()),
])
Performance For large numbers of widgets, lazy-load or paginate widgets to avoid rendering overhead:
MultiWidget::make()
->widgets(WidgetRegistry::get()->take(10)) // Limit to 10 widgets
How can I help you explore Laravel packages today?