Reputation: 19
I'm using filament in version 3 with php 8.4 and Laravel 11.
I have ReportDashboard Page with DepartmentFilter and Multiple Table widget's i will pick one.
In ReportDashboard i declare widgets:
protected function getHeaderWidgets(): array
{
$departments = $this->getDepartments();
return [
DepartmentFilter::make(['departments' => $departments]),
BrokersResults::make(['departments' => $departments]),
];
}
private function getDepartments(): array
{
return Cache::remember('department-list', now()->addDay(), static fn() => User::query()->get();
}
In DepartmentFilter i have code like this:
<?php
namespace App\Filament\Resources\ReportResource\Widgets;
use Filament\Forms\Components\Select;
use Filament\Forms\Concerns\InteractsWithForms;
use Filament\Forms\Contracts\HasForms;
use Filament\Forms\Form;
use Filament\Widgets\Widget;
class DepartmentFilter extends Widget implements HasForms
{
use InteractsWithForms;
protected static string $view = 'filament.widgets.filters';
protected static ?int $sort = 1;
public array $departments = [];
public ?int $departmentId = null;
protected int|string|array $columnSpan = [
'xs' => 1,
'md' => 2,
];
public function form(Form $form): form
{
return $form
->schema(
[
Select::make('department_id')
->label(__('labels.department'))
->selectablePlaceholder(false)
->statePath('departmentId')
->options($this->departments)
->live()
->afterStateUpdated(function (?string $state) {
ray(['departmentFilter', $state ?? array_key_first($this->departments)])->orange();
$this->dispatch(
'departmentChanged',
departmentId: $state ?? array_key_first($this->departments)
);
})
->columnSpanFull()
]
);
}
}
And finally we have BrokersResults
<?php
namespace App\Filament\Resources\ReportResource\Widgets;
use App\Enums\ReportPeriodEnum;
use App\Interfaces\Repositories\ReportRepositoryInterface;
use App\Models\Process\Bank;
use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonPeriod;
use Filament\Forms\Components\Select;
use Filament\Forms\Get;
use Filament\Tables\Columns\TextColumn;
use Filament\Tables\Contracts\HasTable;
use Filament\Tables\Enums\FiltersLayout;
use Filament\Tables\Filters\Filter;
use Filament\Tables\Table;
use Filament\Widgets\Concerns\InteractsWithPageFilters;
use Filament\Widgets\TableWidget as BaseWidget;
use Illuminate\Contracts\Support\Htmlable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Relation;
use Livewire\Attributes\On;
use stdClass;
class BrokersResults extends BaseWidget
{
use InteractsWithPageFilters;
public array $departments = [] {
set {
$this->departments = $value;
$this->departmentId ??= array_key_first($value);
ray(['brokersResults-set', $this->departmentId])->purple();
}
}
protected $listeners = ['departmentChanged' => '$refresh'];
public function __construct(
public ?int $departmentId = null
) {
}
#[On('departmentChanged')]
public function departmentChanged(int $departmentId): void
{
ray(['brokersResults', $departmentId])->purple();
$this->departmentId = $departmentId;
}
//- We use joins and custom grouping logic, so we need to override the recordKey.
public function getTableRecordKey(Model $record): string
{
return $record->user_id;
}
public function table(Table $table): Table
{
return $table
->filters(
[
Filter::make('results_period')
->columnSpanFull()
->resetState(null)
->columns(3)
->form([
Select::make('period')
->label(__('labels.period'))
->default(ReportPeriodEnum::YEARLY->value)
->options(
[
ReportPeriodEnum::MONTHLY->value => __('Monthly'),
ReportPeriodEnum::YEARLY->value => __('Yearly'),
]
)
->selectablePlaceholder(false)
->live(),
Select::make('month')
->default(now()->month)
->hidden(fn(Get $get) => $get('period') === ReportPeriodEnum::YEARLY->value || !$get('period'))
->label(__('labels.month'))
->options(
function () {
return collect(CarbonPeriod::create(now()->startOfYear(), '1 month', now()->endOfYear()))
->map(fn(Carbon $date) => $date->month)
->sortDesc()
->mapWithKeys(fn(int $month) => [$month => __('months.'.$month)]);
}
)
->selectablePlaceholder(false)
->required(),
Select::make('year')
->options(
function () {
return collect(CarbonPeriod::create(now()->subYears(10), '1 year', now()))
->map(fn(Carbon $date) => $date->year)
->sortDesc()
->mapWithKeys(fn(int $year) => [$year => $year]);
}
)
->default(now()->year)
->selectablePlaceholder(false)
->label(__('labels.year'))
->required(),
])
->modifyBaseQueryUsing(function (Builder $query, array $data): Builder {
$periodEnum = ReportPeriodEnum::from($data['period']);
$date = match ($periodEnum) {
ReportPeriodEnum::MONTHLY => CarbonImmutable::create($data['year'], $data['month']),
ReportPeriodEnum::YEARLY => CarbonImmutable::create($data['year']),
};
$period = $periodEnum->getPeriod($date);
return $query->whereBetween('processes_banks.start_date', [
$period->getStartDate(),
$period->getEndDate(),
]);
})
],
layout: FiltersLayout::AboveContent
)
->query($this->getTableQuery())
->columns([
TextColumn::make('index')
->label(__('labels.lp'))
->state(
static function (HasTable $livewire, stdClass $rowLoop): string {
return (string)(
$rowLoop->iteration +
($livewire->getTableRecordsPerPage() * (
$livewire->getTablePage() - 1
))
);
}
),
]);
}
protected function getTableQuery(): Builder|Relation|null
{
return $this->getReportRepository()
->getBrokersResultsQuery($this->departmentId);
}
public function getReportRepository(): ReportRepositoryInterface
{
ray(['getReportRepository', $this->departmentId])->red();
return app(ReportRepositoryInterface::class);
}
protected function getTableHeading(): string|Htmlable|null
{
return __('Best brokers');
}
}
Everything work well in the first render of the page:
But, when i change option in a select:
I get old departmentId in Repository, but in listener i get correct:
It seems like, event is called after getting data from the table, so $this->departmentId is old?
First run: 2166 -> changed to 2167 -> stil 2166 -> changed to 2166 -> i get previous id 2167
Upvotes: 0
Views: 89