mirror of
https://github.com/filamentphp/filament.git
synced 2026-09-01 15:09:33 +08:00
Add table header cell render hook (#17895)
* renderhooks * indenting * add hasRenderHook method * remove table cell renderhook * remove table cell renderhook view * implement hasRenderHook check * rename & document hook --------- Co-authored-by: Dan Harrin <git@danharrin.com>
This commit is contained in:
@@ -133,6 +133,7 @@ use Filament\Tables\View\TablesRenderHook;
|
||||
```
|
||||
|
||||
- `TablesRenderHook::FILTER_INDICATORS` - Replace the existing filter indicators, receives `filterIndicators` data as `array<Filament\Tables\Filters\Indicator>`
|
||||
- `TablesRenderHook::HEADER_CELL` - Replace the existing header cells, receives the `Filament\Tables\Columns\Column` object as `column` and `isReordering` in the data.
|
||||
- `TablesRenderHook::SELECTION_INDICATOR_ACTIONS_AFTER` - After the "select all" and "deselect all" action buttons in the selection indicator bar
|
||||
- `TablesRenderHook::SELECTION_INDICATOR_ACTIONS_BEFORE` - Before the "select all" and "deselect all" action buttons in the selection indicator bar
|
||||
- `TablesRenderHook::HEADER_AFTER` - After the header container
|
||||
|
||||
@@ -10,6 +10,7 @@ use Illuminate\Support\Facades\Facade;
|
||||
/**
|
||||
* @method static bool hasSpaMode(?string $url = null)
|
||||
* @method static bool hasSpaPrefetching()
|
||||
* @method static bool hasRenderHook(string $name, string | array<string> | null $scopes = null)
|
||||
* @method static Htmlable renderHook(string $name, string | array<string> | null $scopes = null, array<string, mixed> $data = [])
|
||||
*
|
||||
* @see ViewManager
|
||||
|
||||
@@ -39,6 +39,30 @@ class ViewManager
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string | array<string> | null $scopes
|
||||
*/
|
||||
public function hasRenderHook(string $name, string | array | null $scopes = null): bool
|
||||
{
|
||||
if (! isset($this->renderHooks[$name])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isset($this->renderHooks[$name][null]) && count($this->renderHooks[$name][null])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$scopes = Arr::wrap($scopes);
|
||||
|
||||
foreach ($scopes as $scopeName) {
|
||||
if (isset($this->renderHooks[$name][$scopeName]) && count($this->renderHooks[$name][$scopeName])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string | array<string> | null $scopes
|
||||
* @param array<string, mixed> $data
|
||||
|
||||
@@ -1347,63 +1347,74 @@
|
||||
@endif
|
||||
@endif
|
||||
|
||||
@php
|
||||
$hasHeaderCellRenderHook = FilamentView::hasRenderHook(TablesRenderHook::HEADER_CELL, scopes: static::class);
|
||||
@endphp
|
||||
|
||||
@foreach ($columns as $column)
|
||||
@php
|
||||
$columnName = $column->getName();
|
||||
$columnLabel = $column->getLabel();
|
||||
$columnAlignment = $column->getAlignment();
|
||||
$columnWidth = $column->getWidth();
|
||||
$isColumnActivelySorted = $getSortColumn() === $column->getName();
|
||||
$isColumnSortable = $column->isSortable() && (! $isReordering);
|
||||
@endphp
|
||||
@if ($hasHeaderCellRenderHook && filled($headerCellView = FilamentView::renderHook(TablesRenderHook::HEADER_CELL, scopes: static::class, data: [
|
||||
'column' => $column,
|
||||
'isReordering' => $isReordering,
|
||||
])))
|
||||
{{ $headerCellView }}
|
||||
@else
|
||||
@php
|
||||
$columnName = $column->getName();
|
||||
$columnLabel = $column->getLabel();
|
||||
$columnAlignment = $column->getAlignment();
|
||||
$columnWidth = $column->getWidth();
|
||||
$isColumnActivelySorted = $getSortColumn() === $column->getName();
|
||||
$isColumnSortable = $column->isSortable() && (! $isReordering);
|
||||
@endphp
|
||||
|
||||
<th
|
||||
@if ($isColumnActivelySorted)
|
||||
aria-sort="{{ $sortDirection === 'asc' ? 'ascending' : 'descending' }}"
|
||||
@endif
|
||||
{{
|
||||
$column->getExtraHeaderAttributeBag()
|
||||
->class([
|
||||
'fi-ta-header-cell',
|
||||
'fi-ta-header-cell-' . str($columnName)->camel()->kebab(),
|
||||
'fi-growable' => blank($columnWidth) && $column->canGrow(default: false),
|
||||
'fi-grouped' => $column->getGroup(),
|
||||
'fi-wrapped' => $column->canHeaderWrap(),
|
||||
'fi-ta-header-cell-sorted' => $isColumnActivelySorted,
|
||||
((($columnAlignment = $column->getAlignment()) instanceof \Filament\Support\Enums\Alignment) ? "fi-align-{$columnAlignment->value}" : (is_string($columnAlignment) ? $columnAlignment : '')),
|
||||
(filled($columnHiddenFrom = $column->getHiddenFrom()) ? "{$columnHiddenFrom}:fi-hidden" : ''),
|
||||
(filled($columnVisibleFrom = $column->getVisibleFrom()) ? "{$columnVisibleFrom}:fi-visible" : ''),
|
||||
])
|
||||
->style([
|
||||
('width: ' . $columnWidth) => filled($columnWidth),
|
||||
])
|
||||
}}
|
||||
>
|
||||
@if ($isColumnSortable)
|
||||
<span
|
||||
aria-label="{{ trim(strip_tags($columnLabel)) }}"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
wire:click="sortTable('{{ $columnName }}')"
|
||||
x-on:keydown.enter.prevent.stop="$wire.sortTable('{{ $columnName }}')"
|
||||
x-on:keydown.space.prevent.stop="$wire.sortTable('{{ $columnName }}')"
|
||||
wire:loading.attr="disabled"
|
||||
class="fi-ta-header-cell-sort-btn"
|
||||
>
|
||||
<th
|
||||
@if ($isColumnActivelySorted)
|
||||
aria-sort="{{ $sortDirection === 'asc' ? 'ascending' : 'descending' }}"
|
||||
@endif
|
||||
{{
|
||||
$column->getExtraHeaderAttributeBag()
|
||||
->class([
|
||||
'fi-ta-header-cell',
|
||||
'fi-ta-header-cell-' . str($columnName)->camel()->kebab(),
|
||||
'fi-growable' => blank($columnWidth) && $column->canGrow(default: false),
|
||||
'fi-grouped' => $column->getGroup(),
|
||||
'fi-wrapped' => $column->canHeaderWrap(),
|
||||
'fi-ta-header-cell-sorted' => $isColumnActivelySorted,
|
||||
((($columnAlignment = $column->getAlignment()) instanceof \Filament\Support\Enums\Alignment) ? "fi-align-{$columnAlignment->value}" : (is_string($columnAlignment) ? $columnAlignment : '')),
|
||||
(filled($columnHiddenFrom = $column->getHiddenFrom()) ? "{$columnHiddenFrom}:fi-hidden" : ''),
|
||||
(filled($columnVisibleFrom = $column->getVisibleFrom()) ? "{$columnVisibleFrom}:fi-visible" : ''),
|
||||
])
|
||||
->style([
|
||||
('width: ' . $columnWidth) => filled($columnWidth),
|
||||
])
|
||||
}}
|
||||
>
|
||||
@if ($isColumnSortable)
|
||||
<span
|
||||
aria-label="{{ trim(strip_tags($columnLabel)) }}"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
wire:click="sortTable('{{ $columnName }}')"
|
||||
x-on:keydown.enter.prevent.stop="$wire.sortTable('{{ $columnName }}')"
|
||||
x-on:keydown.space.prevent.stop="$wire.sortTable('{{ $columnName }}')"
|
||||
wire:loading.attr="disabled"
|
||||
class="fi-ta-header-cell-sort-btn"
|
||||
>
|
||||
{{ $columnLabel }}
|
||||
|
||||
{{
|
||||
\Filament\Support\generate_icon_html(($isColumnActivelySorted && $sortDirection === 'asc') ? \Filament\Support\Icons\Heroicon::ChevronUp : \Filament\Support\Icons\Heroicon::ChevronDown, alias: match (true) {
|
||||
$isColumnActivelySorted && ($sortDirection === 'asc') => \Filament\Tables\View\TablesIconAlias::HEADER_CELL_SORT_ASC_BUTTON,
|
||||
$isColumnActivelySorted && ($sortDirection === 'desc') => \Filament\Tables\View\TablesIconAlias::HEADER_CELL_SORT_DESC_BUTTON,
|
||||
default => \Filament\Tables\View\TablesIconAlias::HEADER_CELL_SORT_BUTTON,
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
@else
|
||||
{{ $columnLabel }}
|
||||
|
||||
{{
|
||||
\Filament\Support\generate_icon_html(($isColumnActivelySorted && $sortDirection === 'asc') ? \Filament\Support\Icons\Heroicon::ChevronUp : \Filament\Support\Icons\Heroicon::ChevronDown, alias: match (true) {
|
||||
$isColumnActivelySorted && ($sortDirection === 'asc') => \Filament\Tables\View\TablesIconAlias::HEADER_CELL_SORT_ASC_BUTTON,
|
||||
$isColumnActivelySorted && ($sortDirection === 'desc') => \Filament\Tables\View\TablesIconAlias::HEADER_CELL_SORT_DESC_BUTTON,
|
||||
default => \Filament\Tables\View\TablesIconAlias::HEADER_CELL_SORT_BUTTON,
|
||||
})
|
||||
}}
|
||||
</span>
|
||||
@else
|
||||
{{ $columnLabel }}
|
||||
@endif
|
||||
</th>
|
||||
@endif
|
||||
</th>
|
||||
@endif
|
||||
@endforeach
|
||||
|
||||
@if ((! $isReordering) && count($records))
|
||||
@@ -1913,8 +1924,7 @@
|
||||
@if ($columnWrapperTag === 'a')
|
||||
{{ \Filament\Support\generate_href_html($columnUrl ?: $recordUrl, $columnUrl ? $column->shouldOpenUrlInNewTab() : $openRecordUrlInNewTab, hasNestedClickEventHandler: true) }}
|
||||
@elseif ($columnWrapperTag === 'button')
|
||||
type
|
||||
="button"
|
||||
type="button"
|
||||
wire:click.prevent.stop="{{ $columnWireClickAction }}"
|
||||
wire:loading.attr="disabled"
|
||||
wire:target="{{ $columnWireClickAction }}"
|
||||
|
||||
@@ -38,6 +38,8 @@ class TablesRenderHook
|
||||
|
||||
const FILTER_INDICATORS = 'tables::filter.indicators';
|
||||
|
||||
const HEADER_CELL = 'tables::header.cell';
|
||||
|
||||
/**
|
||||
* @deprecated Use `TOOLBAR_COLUMN_MANAGER_TRIGGER_AFTER` instead.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user