Filament:使用一个动态 Livewire 过滤器简化多个小部件

210 阅读3分钟

构建小部件

带日期过滤器的表单

显示订单的图表

可视化用户数据的图表

执行以下命令来搭建这些小部件:

php artisan make:filament-widget Filters  
php artisan make:filament-widget OrdersChart --chart  
php artisan make:filament-widget UsersChart --chart

我们选择的图表可视化工具是条形图

接下来,在过滤器小部件中,我们将使用 Filament Forms 集成日期输入元素。该小部件应跨越整个宽度,并通过$sort = 1定位在顶部。

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 $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'), ]),  
]);  
}  
}

resources/views/filament/widgets/filters.blade.php :

<x-filament-widgets::widget>  
<x-filament::section>  
{{ $this->form }}  
</x-filament::section>  
</x-filament-widgets::widget>

一旦这些配置到位,您将在仪表板上看到一个配备双日期输入的小部件,准备好跨多个图表过滤数据。

为了全面了解应用程序的增长,我们将创建User模型和Order模型的可视化表示。这些图表将描述每日创建的新记录,提供对应用程序性能的深入了解。

为了将数据汇集到这些图表中,我们选择了 Filament 推荐的flowframe/laravel-trend包。

composer require flowframe/laravel-trend

让我们深入研究各个图表:

1. Orders Chart 1. 订单图表

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';  
}  
}

2. Users Chart 2. 用户图

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';  
}  
}

实施后,您的仪表板现在将具有两个视觉上令人愉悦的图表,显示过去一周到今天的数据。

想要使用选定的过滤器刷新您的图表吗?这比你想象的要简单!使用 Livewire 事件,您可以在选择过滤器时快速更新多个图表小部件。让我们深入探讨其机制。

1. 配置过滤器小部件

 在 app/Filament/Widgets/Filters.php :

class Filters extends Widget implements HasForms  
{  
// ...  
public function form(Form $form): Form  
{  
return $form  
->statePath('data')  
->schema([  
Grid::make()  
->schema([  
DatePicker::make('from')  
->live()  
->afterStateUpdated(fn (?string $state) => $this->dispatch('updateFromDate', from: $state)),  
DatePicker::make('to')  
->live()  
->afterStateUpdated(fn (?string $state) => $this->dispatch('updateToDate', to: $state)),  
]),  
]);  
}  
}

2. 对图表小部件中的事件做出反应

现在,两个图表小部件都应该准备好响应日期选择事件。

app/Filament/Widgets/OrdersChart.php :

use Livewire\Attributes\On;  
use Illuminate\Support\Carbon;  
class OrdersChart extends ChartWidget  
{  
protected static ?string $heading = 'Orders Chart';  
protected static ?int $sort = 2;  
public Carbon $fromDate;  
public Carbon $toDate;  
// ...  
#[On('updateFromDate')]  
public function updateFromDate(string $from): void  
{  
$this->fromDate = Carbon::parse($from);  
$this->updateChartData();  
}  
#[On('updateToDate')]  
public function updateToDate(string $to): void  
{  
$this->toDate = Carbon::parse($to);  
$this->updateChartData();  
}  
}

做类似的事情 app/Filament/Widgets/UsersChart.php :

use Livewire\Attributes\On;  
use Illuminate\Support\Carbon;  
class UsersChart extends ChartWidget  
{  
protected static ?string $heading = 'Users Chart';  
protected static ?int $sort = 3;  
public Carbon $fromDate;  
public Carbon $toDate;  
// ...  
#[On('updateFromDate')]  
public function updateFromDate(string $from): void  
{  
$this->fromDate = Carbon::make($from);  
$this->updateChartData();  
}  
#[On('updateToDate')]  
public function updateToDate(string $to): void  
{  
$this->toDate = Carbon::make($to);  
$this->updateChartData();  
}  
}

3. 合并新的过滤器数据

鉴于flowframe/laravel-trend包接受 Carbon 实例,我们将日期字符串转换为 Carbon 对象。随后, updateChartData方法确保图表使用新数据恢复活力

在两个图表小部件的getData方法中:

class OrdersChart extends ChartWidget  
{  
// ...  
protected function getData(): array  
{  
$fromDate = $this->fromDate ?? now()->subWeek();  
$toDate = $this->toDate ?? now();  
$data = Trend::model(Order::class)  
->between(start: $fromDate, end: $toDate)  
->perDay()  
->count();  
return [  
'datasets' => [  
[  
'label' => 'Orders',  
'data' => $data->map(fn (TrendValue $value) => $value->aggregate),  
],  
],  
'labels' => $data->map(fn (TrendValue $value) => $value->date),  
];  
}  
}

请记住还要针对用户图表调整此代码片段:

class UsersChart extends ChartWidget  
{  
// ...  
protected function getData(): array  
{  
$fromDate = $this->fromDate ??= now()->subWeek();  
$toDate = $this->toDate ??= now();  
$data = Trend::model(User::class)  
->between(  
start: now()->subWeek(),  
end: now(),  
start: $fromDate,  
end: $toDate,  
)  
->perDay()  
->count();  
return [  
'datasets' => [  
[  
'label' => 'Users',  
'data' => $data->map(fn (TrendValue $value) => $value->aggregate),  
],  
],  
'labels' => $data->map(fn (TrendValue $value) => $value->date),  
];  
}  
// ...  
}

在这种情况下,变量仅被设置为默认值或公共属性。