diff --git a/docs/09-advanced/01-render-hooks.md b/docs/09-advanced/01-render-hooks.md index 0e95e864db..61697728b4 100644 --- a/docs/09-advanced/01-render-hooks.md +++ b/docs/09-advanced/01-render-hooks.md @@ -132,6 +132,7 @@ All these render hooks [can be scoped](#scoping-render-hooks) to any table Livew use Filament\Tables\View\TablesRenderHook; ``` +- `TablesRenderHook::FILTER_INDICATORS` - Replace the existing filter indicators, receives `filterIndicators` data as `array` - `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 @@ -220,6 +221,20 @@ FilamentView::registerRenderHook( ); ``` +## Passing data to render hooks + +Render hooks can receive "data" from when the hook is rendered. To access data from a render hook, you can inject it using an `array $data` parameter to the hook's rendering function: + +```php +use Filament\Support\Facades\FilamentView; +use Filament\Tables\View\TablesRenderHook; + +FilamentView::registerRenderHook( + TablesRenderHook::FILTER_INDICATORS, + fn (array $data): View => view('filter-indicators', ['indicators' => $data['filterIndicators']]), +); +``` + ## Rendering hooks Plugin developers might find it useful to expose render hooks to their users. You do not need to register them anywhere, simply output them in Blade like so: @@ -228,7 +243,7 @@ Plugin developers might find it useful to expose render hooks to their users. Yo {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_START) }} ``` -To provide scope your render hook, you can pass it as the second argument to `renderHook()`. For instance, if your hook is inside a Livewire component, you can pass the class of the component using `static::class`: +To provide [scope](#scoping-render-hooks) your render hook, you can pass it as the second argument to `renderHook()`. For instance, if your hook is inside a Livewire component, you can pass the class of the component using `static::class`: ```blade {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_START, scopes: $this->getRenderHookScopes()) }} @@ -239,3 +254,9 @@ You can even pass multiple scopes as an array, and all render hooks that match a ```blade {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\View\PanelsRenderHook::PAGE_START, scopes: [static::class, \App\Filament\Resources\Users\UserResource::class]) }} ``` + +You can pass [data](#passing-data-to-render-hooks) to a render hook using a `data` argument to the `renderHook()` function: + +```blade +{{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::FILTER_INDICATORS, data: ['filterIndicators' => $filterIndicators]) }} +``` diff --git a/packages/support/src/View/ViewManager.php b/packages/support/src/View/ViewManager.php index 1d5eb328df..c4a32d045b 100644 --- a/packages/support/src/View/ViewManager.php +++ b/packages/support/src/View/ViewManager.php @@ -41,14 +41,15 @@ class ViewManager /** * @param string | array | null $scopes + * @param array $data */ - public function renderHook(string $name, string | array | null $scopes = null): Htmlable + public function renderHook(string $name, string | array | null $scopes = null, array $data = []): Htmlable { $renderedHooks = []; $scopes = Arr::wrap($scopes); - $renderHook = function (callable $hook) use (&$renderedHooks, $scopes): ?string { + $renderHook = function (callable $hook) use (&$renderedHooks, $scopes, $data): ?string { $hookId = spl_object_id($hook); if (in_array($hookId, $renderedHooks)) { @@ -57,7 +58,9 @@ class ViewManager $renderedHooks[] = $hookId; - return (string) app()->call($hook, ['scopes' => $scopes]); + $result = app()->call($hook, ['data' => $data, 'scopes' => $scopes]); + + return (string) $result; }; $hooks = array_map( diff --git a/packages/tables/resources/views/index.blade.php b/packages/tables/resources/views/index.blade.php index 493e1b8d6f..844ccd120a 100644 --- a/packages/tables/resources/views/index.blade.php +++ b/packages/tables/resources/views/index.blade.php @@ -2,12 +2,14 @@ use Filament\Support\Enums\Alignment; use Filament\Support\Enums\VerticalAlignment; use Filament\Support\Enums\Width; + use Filament\Support\Facades\FilamentView; use Filament\Tables\Actions\HeaderActionsPosition; use Filament\Tables\Columns\Column; use Filament\Tables\Columns\ColumnGroup; use Filament\Tables\Enums\FiltersLayout; use Filament\Tables\Enums\RecordActionsPosition; use Filament\Tables\Enums\RecordCheckboxPosition; + use Filament\Tables\View\TablesRenderHook; use Illuminate\Support\Str; use Illuminate\View\ComponentAttributeBag; @@ -163,7 +165,7 @@ x-show="@js($hasHeader) || @js($hasNonBulkToolbarAction) || (getSelectedRecordsCount() && @js(count($toolbarActions)))" class="fi-ta-header-ctn" > - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::HEADER_BEFORE, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::HEADER_BEFORE, scopes: static::class) }} @if ($header) {{ $header }} @@ -202,7 +204,7 @@ @endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::HEADER_AFTER, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::HEADER_AFTER, scopes: static::class) }} @if ($hasFiltersAboveContent)
@endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_BEFORE, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_BEFORE, scopes: static::class) }}
- {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_START, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_START, scopes: static::class) }}
- {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_REORDER_TRIGGER_BEFORE, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_REORDER_TRIGGER_BEFORE, scopes: static::class) }} @if ($isReorderable) {{ $reorderRecordsTriggerAction }} @endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_REORDER_TRIGGER_AFTER, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_REORDER_TRIGGER_AFTER, scopes: static::class) }} @if ((! $isReordering) && count($toolbarActions)) @foreach ($toolbarActions as $action) @@ -255,7 +257,7 @@ @endforeach @endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_GROUPING_SELECTOR_BEFORE, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_GROUPING_SELECTOR_BEFORE, scopes: static::class) }} @if ($areGroupingSettingsVisible)
@endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_GROUPING_SELECTOR_AFTER, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_GROUPING_SELECTOR_AFTER, scopes: static::class) }}
@if ($isGlobalSearchVisible || $hasFiltersDialog || $hasColumnManagerDropdown)
- {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_SEARCH_BEFORE, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_SEARCH_BEFORE, scopes: static::class) }} @if ($isGlobalSearchVisible) @php @@ -417,7 +419,7 @@ /> @endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_SEARCH_AFTER, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_SEARCH_AFTER, scopes: static::class) }} @if ($hasFiltersDialog || $hasColumnManagerDropdown) @if ($hasFiltersDialog) @@ -494,7 +496,7 @@ @endif @endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_COLUMN_MANAGER_TRIGGER_BEFORE, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_COLUMN_MANAGER_TRIGGER_BEFORE, scopes: static::class) }} @if ($hasColumnManagerDropdown) @php @@ -526,15 +528,15 @@ @endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_COLUMN_MANAGER_TRIGGER_AFTER, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_COLUMN_MANAGER_TRIGGER_AFTER, scopes: static::class) }} @endif
@endif - {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_END) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_END) }}
- {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_AFTER) }} + {{ FilamentView::renderHook(TablesRenderHook::TOOLBAR_AFTER) }}
@if ($isReordering) @@ -578,7 +580,7 @@ @if (! $isSelectionDisabled)
- {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::SELECTION_INDICATOR_ACTIONS_BEFORE, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::SELECTION_INDICATOR_ACTIONS_BEFORE, scopes: static::class) }}
- {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::SELECTION_INDICATOR_ACTIONS_AFTER, scopes: static::class) }} + {{ FilamentView::renderHook(TablesRenderHook::SELECTION_INDICATOR_ACTIONS_AFTER, scopes: static::class) }}
@endif
@endif @if ($filterIndicators) -
-
- - {{ __('filament-tables::table.filters.indicator') }} - + @if ($filterIndicatorsView = FilamentView::renderHook(TablesRenderHook::FILTER_INDICATORS, scopes: static::class, data: ['filterIndicators' => $filterIndicators])) + {{ $filterIndicatorsView }} + @else +
+
+ + {{ __('filament-tables::table.filters.indicator') }} + -
- @foreach ($filterIndicators as $indicator) - @php - $indicatorColor = $indicator->getColor(); - @endphp +
+ @foreach ($filterIndicators as $indicator) + @php + $indicatorColor = $indicator->getColor(); + @endphp - - {{ $indicator->getLabel() }} + + {{ $indicator->getLabel() }} - @if ($indicator->isRemovable()) - @php - $indicatorRemoveLivewireClickHandler = $indicator->getRemoveLivewireClickHandler(); - @endphp + @if ($indicator->isRemovable()) + @php + $indicatorRemoveLivewireClickHandler = $indicator->getRemoveLivewireClickHandler(); + @endphp - - @endif - - @endforeach + + @endif + + @endforeach +
-
- @if (collect($filterIndicators)->contains(fn (\Filament\Tables\Filters\Indicator $indicator): bool => $indicator->isRemovable())) - - @endif -
+ @if (collect($filterIndicators)->contains(fn (\Filament\Tables\Filters\Indicator $indicator): bool => $indicator->isRemovable())) + + @endif +
+ @endif @endif @if (((! $content) && (! $hasColumnsLayout)) || ($records === null) || count($records)) diff --git a/packages/tables/src/View/TablesRenderHook.php b/packages/tables/src/View/TablesRenderHook.php index 0135ca915e..281e6f5cb8 100644 --- a/packages/tables/src/View/TablesRenderHook.php +++ b/packages/tables/src/View/TablesRenderHook.php @@ -36,6 +36,8 @@ class TablesRenderHook const TOOLBAR_START = 'tables::toolbar.start'; + const FILTER_INDICATORS = 'tables::filter.indicators'; + /** * @deprecated Use `TOOLBAR_COLUMN_MANAGER_TRIGGER_AFTER` instead. */ diff --git a/tests/src/Support/RenderHooksTest.php b/tests/src/Support/RenderHooksTest.php index 48137ca308..41eb2346fa 100644 --- a/tests/src/Support/RenderHooksTest.php +++ b/tests/src/Support/RenderHooksTest.php @@ -28,7 +28,7 @@ test('render hooks can render view files', function (): void { ->toHtml()->toContain('bar'); }); -test('render hooks can be scopes:d', function (): void { +test('render hooks can be scoped', function (): void { FilamentView::registerRenderHook('foo', function (): string { return Blade::render('bar'); }); @@ -42,7 +42,7 @@ test('render hooks can be scopes:d', function (): void { ->toHtml()->toBe('barbar'); }); -test('render hooks can be scopes:d to multiple scopes:s', function (): void { +test('render hooks can be scoped to multiple scoped', function (): void { FilamentView::registerRenderHook('foo', function (): string { return Blade::render('bar'); }); @@ -60,7 +60,7 @@ test('render hooks can be scopes:d to multiple scopes:s', function (): void { ->toHtml()->toBe('barbar'); }); -test('render hooks can be scopes:d to multiple scopes:s but only ever output once', function (): void { +test('render hooks can be scoped to multiple scoped but only ever output once', function (): void { FilamentView::registerRenderHook('foo', function (): string { return Blade::render('bar'); }); @@ -73,3 +73,13 @@ test('render hooks can be scopes:d to multiple scopes:s but only ever output onc ->toBeInstanceOf(HtmlString::class) ->toHtml()->toBe('barbar'); }); + +test('render hooks can be passed data', function (): void { + FilamentView::registerRenderHook('foo', function ($data): string { + return $data['foo']; + }); + + expect(FilamentView::renderHook('foo', data: ['foo' => 'bar'])) + ->toBeInstanceOf(HtmlString::class) + ->toHtml()->toBe('bar'); +});