mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-24 15:42:09 +08:00
Merge pull request #9293 from filamentphp/new-table-filters-indicator-api
New table filters indicator API
This commit is contained in:
@@ -41,6 +41,7 @@ use Filament\Tables\Contracts\HasTable;
|
||||
use Filament\Tables\Enums\ActionsPosition;
|
||||
use Filament\Tables\Enums\FiltersLayout;
|
||||
use Filament\Tables\Filters\Filter;
|
||||
use Filament\Tables\Filters\Indicator;
|
||||
use Filament\Tables\Filters\SelectFilter;
|
||||
use Filament\Tables\Grouping\Group;
|
||||
use Filament\Tables\Table;
|
||||
@@ -709,8 +710,10 @@ class TablesDemo extends Component implements HasForms, HasTable
|
||||
->filters([
|
||||
Filter::make('dummy')
|
||||
->indicateUsing(fn () => [
|
||||
'one' => 'Posted by administrator',
|
||||
'two' => 'Less than 1 year old',
|
||||
Indicator::make('Posted by administrator')
|
||||
->removeField('one'),
|
||||
Indicator::make('Less than 1 year old')
|
||||
->removeField('two'),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -345,6 +345,7 @@ You may even render multiple indicators at once, by returning an array. If you h
|
||||
```php
|
||||
use Filament\Forms\Components\DatePicker;
|
||||
use Filament\Tables\Filters\Filter;
|
||||
use Filament\Tables\Filters\Indicator;
|
||||
|
||||
Filter::make('created_at')
|
||||
->form([
|
||||
@@ -356,11 +357,13 @@ Filter::make('created_at')
|
||||
$indicators = [];
|
||||
|
||||
if ($data['from'] ?? null) {
|
||||
$indicators['from'] = 'Created from ' . Carbon::parse($data['from'])->toFormattedDateString();
|
||||
$indicators[] = Indicator::make('Created from ' . Carbon::parse($data['from'])->toFormattedDateString())
|
||||
->removeField('from');
|
||||
}
|
||||
|
||||
if ($data['until'] ?? null) {
|
||||
$indicators['until'] = 'Created until ' . Carbon::parse($data['until'])->toFormattedDateString();
|
||||
$indicators[] = Indicator::make('Created until ' . Carbon::parse($data['until'])->toFormattedDateString())
|
||||
->removeField('until');
|
||||
}
|
||||
|
||||
return $indicators;
|
||||
|
||||
@@ -13,17 +13,19 @@
|
||||
</span>
|
||||
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
@foreach ($indicators as $wireClickHandler => $label)
|
||||
<x-filament::badge>
|
||||
{{ $label }}
|
||||
@foreach ($indicators as $indicator)
|
||||
<x-filament::badge :color="$indicator->getColor()">
|
||||
{{ $indicator->getLabel() }}
|
||||
|
||||
<x-slot
|
||||
name="deleteButton"
|
||||
:label="__('filament-tables::table.filters.actions.remove.label')"
|
||||
wire:click="{{ $wireClickHandler }}"
|
||||
wire:loading.attr="disabled"
|
||||
wire:target="removeTableFilter"
|
||||
></x-slot>
|
||||
@if ($indicator->isRemovable())
|
||||
<x-slot
|
||||
name="deleteButton"
|
||||
:label="__('filament-tables::table.filters.actions.remove.label')"
|
||||
wire:click="{{ $indicator->getRemoveLivewireClickHandler() }}"
|
||||
wire:loading.attr="disabled"
|
||||
wire:target="removeTableFilter"
|
||||
></x-slot>
|
||||
@endif
|
||||
</x-filament::badge>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
@@ -14,26 +14,7 @@
|
||||
$content = $getContent();
|
||||
$contentGrid = $getContentGrid();
|
||||
$contentFooter = $getContentFooter();
|
||||
$filterIndicators = [
|
||||
...($hasSearch() ? ['resetTableSearch' => $getSearchIndicator()] : []),
|
||||
...collect($getColumnSearchIndicators())
|
||||
->mapWithKeys(fn (string $indicator, string $column): array => [
|
||||
"resetTableColumnSearch('{$column}')" => $indicator,
|
||||
])
|
||||
->all(),
|
||||
...array_reduce(
|
||||
$getFilters(),
|
||||
fn (array $carry, \Filament\Tables\Filters\BaseFilter $filter): array => [
|
||||
...$carry,
|
||||
...collect($filter->getIndicators())
|
||||
->mapWithKeys(fn (string $label, int | string $field) => [
|
||||
"removeTableFilter('{$filter->getName()}'" . (is_string($field) ? ' , \'' . $field . '\'' : null) . ')' => $label,
|
||||
])
|
||||
->all(),
|
||||
],
|
||||
[],
|
||||
),
|
||||
];
|
||||
$filterIndicators = $getFilterIndicators();
|
||||
$hasColumnsLayout = $hasColumnsLayout();
|
||||
$hasSummary = $hasSummary();
|
||||
$header = $getHeader();
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace Filament\Tables\Concerns;
|
||||
|
||||
use Filament\Tables\Filters\Indicator;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Arr;
|
||||
use RecursiveArrayIterator;
|
||||
@@ -174,13 +175,14 @@ trait CanSearchRecords
|
||||
$this->updatedTableColumnSearches();
|
||||
}
|
||||
|
||||
public function getTableSearchIndicator(): string
|
||||
public function getTableSearchIndicator(): Indicator
|
||||
{
|
||||
return __('filament-tables::table.fields.search.indicator') . ': ' . $this->getTableSearch();
|
||||
return Indicator::make(__('filament-tables::table.fields.search.indicator') . ': ' . $this->getTableSearch())
|
||||
->removeLivewireClickHandler('resetTableSearch');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
* @return array<Indicator>
|
||||
*/
|
||||
public function getTableColumnSearchIndicators(): array
|
||||
{
|
||||
@@ -203,7 +205,8 @@ trait CanSearchRecords
|
||||
continue;
|
||||
}
|
||||
|
||||
$indicators[$columnName] = "{$column->getLabel()}: {$search}";
|
||||
$indicators[] = Indicator::make("{$column->getLabel()}: {$search}")
|
||||
->removeLivewireClickHandler("resetTableColumnSearch('{$columnName}')");
|
||||
}
|
||||
|
||||
return $indicators;
|
||||
|
||||
@@ -6,6 +6,7 @@ use Filament\Forms\Form;
|
||||
use Filament\Support\Contracts\TranslatableContentDriver;
|
||||
use Filament\Tables\Actions\Action;
|
||||
use Filament\Tables\Actions\BulkAction;
|
||||
use Filament\Tables\Filters\Indicator;
|
||||
use Filament\Tables\Grouping\Group;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Contracts\Pagination\Paginator;
|
||||
@@ -93,10 +94,10 @@ interface HasTable
|
||||
|
||||
public function resetTableColumnSearch(string $column): void;
|
||||
|
||||
public function getTableSearchIndicator(): string;
|
||||
public function getTableSearchIndicator(): Indicator;
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
* @return array<Indicator>
|
||||
*/
|
||||
public function getTableColumnSearchIndicators(): array;
|
||||
|
||||
|
||||
@@ -3,15 +3,16 @@
|
||||
namespace Filament\Tables\Filters\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Filament\Tables\Filters\Indicator;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
trait HasIndicators
|
||||
{
|
||||
protected string | Closure | null $indicateUsing = null;
|
||||
|
||||
protected string | Closure | null $indicator = null;
|
||||
protected Indicator | string | Closure | null $indicator = null;
|
||||
|
||||
public function indicator(string | Closure | null $indicator): static
|
||||
public function indicator(Indicator | string | Closure | null $indicator): static
|
||||
{
|
||||
$this->indicator = $indicator;
|
||||
|
||||
@@ -26,7 +27,7 @@ trait HasIndicators
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string>
|
||||
* @return array<Indicator>
|
||||
*/
|
||||
public function getIndicators(): array
|
||||
{
|
||||
@@ -41,10 +42,24 @@ trait HasIndicators
|
||||
return [];
|
||||
}
|
||||
|
||||
return Arr::wrap($indicators);
|
||||
$indicators = Arr::wrap($indicators);
|
||||
|
||||
foreach ($indicators as $field => $indicator) {
|
||||
if (! $indicator instanceof Indicator) {
|
||||
$indicator = Indicator::make($indicator);
|
||||
}
|
||||
|
||||
if (is_string($field)) {
|
||||
$indicator = $indicator->removeField($field);
|
||||
}
|
||||
|
||||
$indicators[$field] = $indicator;
|
||||
}
|
||||
|
||||
return $indicators;
|
||||
}
|
||||
|
||||
public function getIndicator(): string
|
||||
public function getIndicator(): Indicator | string
|
||||
{
|
||||
$state = $this->getState();
|
||||
|
||||
|
||||
@@ -19,7 +19,13 @@ class Filter extends BaseFilter
|
||||
return [];
|
||||
}
|
||||
|
||||
return [$this->getIndicator()];
|
||||
$indicator = $this->getIndicator();
|
||||
|
||||
if (! $indicator instanceof Indicator) {
|
||||
$indicator = Indicator::make($indicator);
|
||||
}
|
||||
|
||||
return [$indicator];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Tables\Filters;
|
||||
|
||||
use Closure;
|
||||
use Filament\Support\Components\Component;
|
||||
use Filament\Support\Concerns\HasColor;
|
||||
|
||||
class Indicator extends Component
|
||||
{
|
||||
use HasColor;
|
||||
|
||||
protected bool | Closure $isRemovable = true;
|
||||
|
||||
protected string | Closure | null $label = null;
|
||||
|
||||
protected string | Closure | null $removeField = null;
|
||||
|
||||
protected string | Closure | null $removeLivewireClickHandler = null;
|
||||
|
||||
public function __construct(string $label)
|
||||
{
|
||||
$this->label($label);
|
||||
}
|
||||
|
||||
public static function make(string | Closure | null $label = null): static
|
||||
{
|
||||
return app(static::class, ['label' => $label]);
|
||||
}
|
||||
|
||||
public function label(string $label): static
|
||||
{
|
||||
$this->label = $label;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getLabel(): string
|
||||
{
|
||||
return $this->label;
|
||||
}
|
||||
|
||||
public function removable(bool | Closure $condition = true): static
|
||||
{
|
||||
$this->isRemovable = $condition;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function isRemovable(): bool
|
||||
{
|
||||
return (bool) $this->evaluate($this->isRemovable);
|
||||
}
|
||||
|
||||
public function removeField(string | Closure | null $name): static
|
||||
{
|
||||
$this->removeField = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRemoveField(): ?string
|
||||
{
|
||||
return $this->evaluate($this->removeField);
|
||||
}
|
||||
|
||||
public function removeLivewireClickHandler(string | Closure | null $handler): static
|
||||
{
|
||||
$this->removeLivewireClickHandler = $handler;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRemoveLivewireClickHandler(): ?string
|
||||
{
|
||||
return $this->evaluate($this->removeLivewireClickHandler);
|
||||
}
|
||||
}
|
||||
@@ -66,7 +66,13 @@ class SelectFilter extends BaseFilter
|
||||
|
||||
$labels = collect($labels)->join(', ', ' & ');
|
||||
|
||||
return ["{$filter->getIndicator()}: {$labels}"];
|
||||
$indicator = $filter->getIndicator();
|
||||
|
||||
if (! $indicator instanceof Indicator) {
|
||||
$indicator = Indicator::make("{$indicator}: {$labels}");
|
||||
}
|
||||
|
||||
return [$indicator];
|
||||
}
|
||||
|
||||
if (blank($state['value'] ?? null)) {
|
||||
@@ -86,7 +92,13 @@ class SelectFilter extends BaseFilter
|
||||
return [];
|
||||
}
|
||||
|
||||
return ["{$filter->getIndicator()}: {$label}"];
|
||||
$indicator = $filter->getIndicator();
|
||||
|
||||
if (! $indicator instanceof Indicator) {
|
||||
$indicator = Indicator::make("{$indicator}: {$label}");
|
||||
}
|
||||
|
||||
return [$indicator];
|
||||
});
|
||||
|
||||
$this->resetState(['value' => null]);
|
||||
|
||||
@@ -22,16 +22,22 @@ class TernaryFilter extends SelectFilter
|
||||
|
||||
$this->boolean();
|
||||
|
||||
$this->indicateUsing(function (array $state): array {
|
||||
$this->indicateUsing(function (TernaryFilter $filter, array $state): array {
|
||||
if (blank($state['value'] ?? null)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$stateLabel = $state['value'] ?
|
||||
$this->getTrueLabel() :
|
||||
$this->getFalseLabel();
|
||||
$filter->getTrueLabel() :
|
||||
$filter->getFalseLabel();
|
||||
|
||||
return ["{$this->getIndicator()}: {$stateLabel}"];
|
||||
$indicator = $filter->getIndicator();
|
||||
|
||||
if (! $indicator instanceof Indicator) {
|
||||
$indicator = Indicator::make("{$indicator}: {$stateLabel}");
|
||||
}
|
||||
|
||||
return [$indicator];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -36,14 +36,14 @@ class TrashedFilter extends TernaryFilter
|
||||
|
||||
$this->indicateUsing(function (array $state): array {
|
||||
if ($state['value'] ?? null) {
|
||||
return [$this->getTrueLabel()];
|
||||
return [Indicator::make($this->getTrueLabel())];
|
||||
}
|
||||
|
||||
if (blank($state['value'] ?? null)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [$this->getFalseLabel()];
|
||||
return [Indicator::make($this->getFalseLabel())];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ class Table extends ViewComponent
|
||||
use Table\Concerns\HasColumns;
|
||||
use Table\Concerns\HasContent;
|
||||
use Table\Concerns\HasEmptyState;
|
||||
use Table\Concerns\HasFilterIndicators;
|
||||
use Table\Concerns\HasFilters;
|
||||
use Table\Concerns\HasHeader;
|
||||
use Table\Concerns\HasHeaderActions;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Filament\Tables\Table\Concerns;
|
||||
|
||||
use Closure;
|
||||
use Filament\Tables\Filters\Indicator;
|
||||
|
||||
trait CanSearchRecords
|
||||
{
|
||||
@@ -79,13 +80,13 @@ trait CanSearchRecords
|
||||
return $this->getLivewire()->hasTableSearch();
|
||||
}
|
||||
|
||||
public function getSearchIndicator(): string
|
||||
public function getSearchIndicator(): Indicator
|
||||
{
|
||||
return $this->getLivewire()->getTableSearchIndicator();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, string>
|
||||
* @return array<Indicator> | array<string, string>
|
||||
*/
|
||||
public function getColumnSearchIndicators(): array
|
||||
{
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
namespace Filament\Tables\Table\Concerns;
|
||||
|
||||
use Filament\Tables\Filters\BaseFilter;
|
||||
use Filament\Tables\Filters\Indicator;
|
||||
|
||||
trait HasFilterIndicators
|
||||
{
|
||||
/**
|
||||
* @return array<Indicator>
|
||||
*/
|
||||
public function getFilterIndicators(): array
|
||||
{
|
||||
return [
|
||||
...($this->hasSearch() ? [$this->getSearchIndicator()] : []),
|
||||
...$this->getColumnSearchIndicators(),
|
||||
...array_reduce(
|
||||
$this->getFilters(),
|
||||
fn (array $carry, BaseFilter $filter): array => [
|
||||
...$carry,
|
||||
...collect($filter->getIndicators())
|
||||
->map(function (Indicator $indicator) use ($filter): Indicator {
|
||||
$removeField = $indicator->getRemoveField();
|
||||
|
||||
return $indicator->removeLivewireClickHandler("removeTableFilter('{$filter->getName()}'" . (filled($removeField) ? ', \'' . $removeField . '\'' : null) . ')');
|
||||
})
|
||||
->all(),
|
||||
],
|
||||
[],
|
||||
),
|
||||
];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user