In Filament, adding a filter to dashboard widgets is pretty straightforward. But what if you want to have a filter that would update MULTIPLE widgets at once, similar to Google Analytics? We need to use events and Livewire properties for this. Let's take a look.
Widgets
First, let's create the widgets. We will need three widgets:
- Form with date filters
- Chart with orders
- Chart with Users
php artisan make:filament-widget Filtersphp artisan make:filament-widget OrdersChart --chartphp artisan make:filament-widget UsersChart --chart
For the charts, I will be using the bar type.
Now, let's show date inputs in the Filters
widget with Filament Forms. Also, the Filters
widget needs to be full width and have the $sort = 1
to be on top.
app/Filament/Widgets/Filters.php:
use Filament\Forms\Form;use Filament\Forms\Components\Grid;use Filament\Forms\Contracts\HasForms;use Filament\Forms\Components\DatePicker;use Filament\Forms\Concerns\InteractsWithForms; class Filters extends Widget implements HasForms{ use InteractsWithForms; protected static string $view = 'filament.widgets.filters'; protected int | string | array $columnSpan = 'full'; protected static ?int $sort = 1; public ?array $data = []; public function form(Form $form): Form { return $form ->statePath('data') ->schema([ Grid::make() ->schema([ DatePicker::make('from'), DatePicker::make('to'), ]), ]); }}
In the dashboard, we now have a widget with two date inputs.
For the other two widgets, we will show a chart of two models, User
and Order
. These charts will show how many new records are created daily.
For passing data to the chart, we will use the package recommended by Filament flowframe/laravel-trend
.
composer require flowframe/laravel-trend
And for the charts.
app/Filament/Widgets/OrdersChart.php:
use App\Models\Order;use Flowframe\Trend\Trend;use Flowframe\Trend\TrendValue;use Filament\Widgets\ChartWidget; class OrdersChart extends ChartWidget{ protected static ?string $heading = 'Orders Chart'; protected static ?int $sort = 2; protected function getData(): array { $data = Trend::model(Order::class) ->between( start: now()->subWeek(), end: now(), ) ->perDay() ->count(); return [ 'datasets' => [ [ 'label' => 'Orders', 'data' => $data->map(fn (TrendValue $value) => $value->aggregate), ], ], 'labels' => $data->map(fn (TrendValue $value) => $value->date), ]; } protected function getType(): string { return 'bar'; }}
app/Filament/Widgets/UsersChart.php:
use App\Models\User;use Flowframe\Trend\Trend;use Flowframe\Trend\TrendValue;use Filament\Widgets\ChartWidget; class UsersChart extends ChartWidget{ protected static ?string $heading = 'Users Chart'; protected static ?int $sort = 3; protected function getData(): array { $data = Trend::model(User::class) ->between( start: now()->subWeek(), end: now(), ) ->perDay() ->count(); return [ 'datasets' => [ [ 'label' => 'Users', 'data' => $data->map(fn (TrendValue $value) => $value->aggregate), ], ], 'labels' => $data->map(fn (TrendValue $value) => $value->date), ]; } protected function getType(): string { return 'bar'; }}
We also have two charts in the dashboard showing data from the week to now.
Updating Charts
So now, let's update the charts when a filter is selected. To achieve this, we will need to...