filamentphp / filament

A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS.
https://filamentphp.com
MIT License
19.08k stars 2.94k forks source link

FilamentPHP filter not updating the record count #7187

Closed Umar-Farooq-Shafi closed 1 year ago

Umar-Farooq-Shafi commented 1 year ago

Package

filament/filament

Package Version

2.0

Laravel Version

10

Livewire Version

2.11

PHP Version

8.1

Problem description

The Laravel FilamentPHP filter query not updating the records.

I've UserResource and a column which is some of the entries of another table. I added the from and until filter in the table and when I try to update the counts, it's not updating.

public static function table(Table $table): Table
    {
        return $table
            ->columns([
                Tables\Columns\TextColumn::make('name')
                    ->sortable()
                    ->searchable()
                    ->toggleable(),
                Tables\Columns\TextColumn::make('email')
                    ->sortable()
                    ->searchable()
                    ->toggleable(),
                Tables\Columns\TextColumn::make('hospital.name')
                    ->sortable()
                    ->toggleable()
                    ->searchable(),
                Tables\Columns\TextColumn::make('contact_number')
                    ->sortable()
                    ->toggleable()
                    ->toggledHiddenByDefault()
                    ->searchable(),
                Tables\Columns\TextColumn::make('alliedHealthProfessional.designation')
                    ->label('Designation')
                    ->enum(FilamentFormHelper::getDesignations())
                    ->sortable()
                    ->toggleable()
                    ->searchable(),
                Tables\Columns\TextColumn::make('surgeries_count')
                    ->label('Entries')
                    ->counts('surgeries')
                    ->sortable()
                    ->toggleable()
            ])
            ->filters([
                Filter::make('created_at')
                    ->form([
                        Forms\Components\DatePicker::make('created_from'),
                        Forms\Components\DatePicker::make('created_until'),
                    ])
                    ->query(function (Builder $query, array $data): Builder {
                        return $query->withCount([
                            'surgeries as surgeries_count' => function (Builder $builder) use ($data) {
                                if ($from = $data['created_from'])
                                    $builder->where('surgeries.date', '>=', $from);
                                if ($until = $data['created_until'])
                                    $builder->where('surgeries.date', '<=', $until);

                                return $builder;
                            }
                        ]);
                    })
            ]);
    }

Expected behavior

The Entries column should update the count according to the filter. here is the demo.

Steps to reproduce

Add the from and until date filter in the filament resource table with the counts of relation 1:N table.

Reproduction repository

https://github.com/Umar-Farooq-Shafi/filament-filter-issue

Relevant log output

No response

zepfietje commented 1 year ago

The constraints from the filter aren't applied to the relationship count. Make sure to add the relationship query constraints to the counts() method like so:

counts(['surgeries' => function (Builder $query) {
    // ...
}])
Umar-Farooq-Shafi commented 1 year ago

@zepfietje I don't want to apply constraints on the counts(). I want update the counts base on the date filter

Umar-Farooq-Shafi commented 1 year ago

why is this close? any solution or workaround? @zepfietje

zepfietje commented 1 year ago

You should access the active filters and apply the constraint to the counts() method as I explained above. That's the solution. 🙂

Umar-Farooq-Shafi commented 1 year ago

sorry, what is the sentex to access the active filter?

zepfietje commented 1 year ago

Something along those lines:

function (Builder $query, HasTable $livewire) {
    $livewire->getTableFilterState('created_at');
}
Umar-Farooq-Shafi commented 1 year ago

getting error

Too few arguments to function App\Filament\Resources\UserResource::App\Filament\Resources\
{closure}(), 1 passed in /Users/dev/Desktop/Personal/PMU/pmu-
ahp/vendor/laravel/framework/src/Illuminate/Database/Eloquent/Builder.php on line 1603 and
 exactly 2 expected
Umar-Farooq-Shafi commented 1 year ago
Tables\Columns\TextColumn::make('surgeries_count')
                    ->label('Entries')
                    ->counts(['surgeries' => function (Builder $query, HasTable $livewire) {
                        dd($livewire->getTableFilterState('created_from'));
                    }])
                    ->sortable()
                    ->toggleable(),
zepfietje commented 1 year ago

Could you share more context of the error using a Flare exception link?

Umar-Farooq-Shafi commented 1 year ago

https://flareapp.io/share/B5ZAWWp7 @zepfietje

zepfietje commented 1 year ago

Ah right, $livewire is probably not injected there. Since this question isn't really a bug, could you ask for help in the #help channel in the Filament Discord server? https://discord.gg/filament

I'm too busy working on finishing v3 at the moment, sorry.

Umar-Farooq-Shafi commented 1 year ago
Screen Shot 2023-07-25 at 12 48 11 PM

I do not have permission to create a post. can you please help me?

danharrin commented 1 year ago

click the button at the top to complete onboarding first

Umar-Farooq-Shafi commented 1 year ago

thanks @danharrin

goyote commented 2 months ago

@Umar-Farooq-Shafi did you find an answer for this?

Umar-Farooq-Shafi commented 2 months ago

Yes, I added the following function inside the ListRecord class

protected function getTableQuery(): Builder
    {
        if (is_null($this->tableFilters)) {
            return parent::getTableQuery()->withCount('patients');
        }

        $data = data_get($this->tableFilters, 'date', []);

        return parent::getTableQuery()->withCount([
            'patients as patients_count' => function (Builder $builder) use ($data) {
                $from = data_get($data, 'from');
                $until = data_get($data, 'until');

                if (! is_null($from) && $from !== 'null') {
                    $builder->where('patients.date', '>=', $from);
                }

                if (! is_null($until) && $until !== 'null') {
                    $builder->where('patients.date', '<=', $until);
                }

                return $builder;
            },
        ])
            ->withoutGlobalScopes([
                SoftDeletingScope::class,
            ]);
    }