├── CHANGELOG.md ├── src ├── Testing │ └── TestsFilamentSelectTable.php ├── Facades │ └── FilamentSelectTable.php ├── Commands │ └── FilamentSelectTableCommand.php ├── FilamentSelectTableServiceProvider.php ├── FilamentSelectTable.php └── Forms │ └── SelectTable.php ├── LICENSE.md ├── bin └── build.js ├── composer.json ├── README.md └── resources └── views └── index.blade.php /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to `filament-select-table` will be documented in this file. 4 | 5 | ## 1.0.0 - 202X-XX-XX 6 | 7 | - initial release 8 | -------------------------------------------------------------------------------- /src/Testing/TestsFilamentSelectTable.php: -------------------------------------------------------------------------------- 1 | comment('All done'); 16 | 17 | return self::SUCCESS; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Elmudo-Dev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /bin/build.js: -------------------------------------------------------------------------------- 1 | import esbuild from 'esbuild' 2 | 3 | const isDev = process.argv.includes('--dev') 4 | 5 | async function compile(options) { 6 | const context = await esbuild.context(options) 7 | 8 | if (isDev) { 9 | await context.watch() 10 | } else { 11 | await context.rebuild() 12 | await context.dispose() 13 | } 14 | } 15 | 16 | const defaultOptions = { 17 | define: { 18 | 'process.env.NODE_ENV': isDev ? `'development'` : `'production'`, 19 | }, 20 | bundle: true, 21 | mainFields: ['module', 'main'], 22 | platform: 'neutral', 23 | sourcemap: isDev ? 'inline' : false, 24 | sourcesContent: isDev, 25 | treeShaking: true, 26 | target: ['es2020'], 27 | minify: !isDev, 28 | plugins: [{ 29 | name: 'watchPlugin', 30 | setup: function (build) { 31 | build.onStart(() => { 32 | console.log(`Build started at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`) 33 | }) 34 | 35 | build.onEnd((result) => { 36 | if (result.errors.length > 0) { 37 | console.log(`Build failed at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`, result.errors) 38 | } else { 39 | console.log(`Build finished at ${new Date(Date.now()).toLocaleTimeString()}: ${build.initialOptions.outfile}`) 40 | } 41 | }) 42 | } 43 | }], 44 | } 45 | 46 | compile({ 47 | ...defaultOptions, 48 | entryPoints: ['./resources/js/index.js'], 49 | outfile: './resources/dist/filament-select-table.js', 50 | }) 51 | -------------------------------------------------------------------------------- /src/FilamentSelectTableServiceProvider.php: -------------------------------------------------------------------------------- 1 | name(static::$name) 27 | ->hasCommands($this->getCommands()) 28 | ->hasInstallCommand(function (InstallCommand $command) { 29 | $command 30 | ->askToStarRepoOnGitHub('elmudo-dev/filament-select-table'); 31 | }); 32 | 33 | if (file_exists($package->basePath('/../resources/lang'))) { 34 | $package->hasTranslations(); 35 | } 36 | 37 | if (file_exists($package->basePath('/../resources/views'))) { 38 | $package->hasViews(static::$viewNamespace); 39 | } 40 | } 41 | 42 | public function packageRegistered(): void {} 43 | 44 | public function packageBooted(): void 45 | { 46 | $this->registerLivewireComponents(); 47 | 48 | FilamentAsset::registerScriptData( 49 | $this->getScriptData() 50 | ); 51 | 52 | // Testing 53 | Testable::mixin(new TestsFilamentSelectTable); 54 | } 55 | 56 | private function registerLivewireComponents(): void 57 | { 58 | \Livewire\Livewire::component('elmudo-dev::filament-select-table', FilamentSelectTable::class); 59 | } 60 | 61 | /** 62 | * @return array 63 | */ 64 | protected function getCommands(): array 65 | { 66 | return [ 67 | FilamentSelectTableCommand::class, 68 | ]; 69 | } 70 | 71 | /** 72 | * @return array 73 | */ 74 | protected function getRoutes(): array 75 | { 76 | return []; 77 | } 78 | 79 | /** 80 | * @return array 81 | */ 82 | protected function getScriptData(): array 83 | { 84 | return []; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "elmudo-dev/filament-select-table", 3 | "description": "This package is an extension of select to allow selecting from a table", 4 | "keywords": [ 5 | "Elmudo-Dev", 6 | "laravel", 7 | "filament-select-table" 8 | ], 9 | "homepage": "https://github.com/elmudometal/filament-select-table", 10 | "support": { 11 | "issues": "https://github.com/elmudometal/filament-select-table/issues", 12 | "source": "https://github.com/elmudometal/filament-select-table" 13 | }, 14 | "license": "MIT", 15 | "authors": [ 16 | { 17 | "name": "Hernan Soto", 18 | "email": "elmudometal@gmail.com", 19 | "role": "Developer" 20 | } 21 | ], 22 | "require": { 23 | "php": "^8.1", 24 | "filament/forms": "^3.0", 25 | "filament/tables": "^3.0", 26 | "spatie/laravel-package-tools": "^1.15.0" 27 | }, 28 | "require-dev": { 29 | "laravel/pint": "^1.0", 30 | "nunomaduro/collision": "^7.9", 31 | "nunomaduro/larastan": "^2.0.1", 32 | "orchestra/testbench": "^8.0", 33 | "pestphp/pest": "^2.1", 34 | "pestphp/pest-plugin-arch": "^2.0", 35 | "pestphp/pest-plugin-laravel": "^2.0", 36 | "phpstan/extension-installer": "^1.1", 37 | "phpstan/phpstan-deprecation-rules": "^1.0", 38 | "phpstan/phpstan-phpunit": "^1.0", 39 | "spatie/laravel-ray": "^1.26" 40 | }, 41 | "autoload": { 42 | "psr-4": { 43 | "ElmudoDev\\FilamentSelectTable\\": "src/" 44 | } 45 | }, 46 | "autoload-dev": { 47 | "psr-4": { 48 | "ElmudoDev\\FilamentSelectTable\\Tests\\": "tests/" 49 | } 50 | }, 51 | "scripts": { 52 | "post-autoload-dump": "@php ./vendor/bin/testbench package:discover --ansi", 53 | "analyse": "vendor/bin/phpstan analyse", 54 | "test": "vendor/bin/pest", 55 | "test-coverage": "vendor/bin/pest --coverage", 56 | "format": "vendor/bin/pint" 57 | }, 58 | "config": { 59 | "sort-packages": true, 60 | "allow-plugins": { 61 | "pestphp/pest-plugin": true, 62 | "phpstan/extension-installer": true 63 | } 64 | }, 65 | "extra": { 66 | "laravel": { 67 | "providers": [ 68 | "ElmudoDev\\FilamentSelectTable\\FilamentSelectTableServiceProvider" 69 | ], 70 | "aliases": { 71 | "FilamentSelectTable": "ElmudoDev\\FilamentSelectTable\\Facades\\FilamentSelectTable" 72 | } 73 | } 74 | }, 75 | "minimum-stability": "dev", 76 | "prefer-stable": true 77 | } 78 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This package is an extension of select to allow selecting from a table 2 | 3 | [![Latest Version on Packagist](https://img.shields.io/packagist/v/elmudo-dev/filament-select-table.svg?style=flat-square)](https://packagist.org/packages/elmudo-dev/filament-select-table) 4 | [![GitHub Tests Action Status](https://img.shields.io/github/actions/workflow/status/elmudo-dev/filament-select-table/run-tests.yml?branch=main&label=tests&style=flat-square)](https://github.com/elmudometal/filament-select-table/actions?query=workflow%3Arun-tests+branch%3Amain) 5 | [![GitHub Code Style Action Status](https://img.shields.io/github/actions/workflow/status/elmudo-dev/filament-select-table/fix-php-code-styling.yml?branch=main&label=code%20style&style=flat-square)](https://github.com/elmudometal/filament-select-table/actions?query=workflow%3A"Fix+PHP+code+styling"+branch%3Amain) 6 | [![Total Downloads](https://img.shields.io/packagist/dt/elmudo-dev/filament-select-table.svg?style=flat-square)](https://packagist.org/packages/elmudo-dev/filament-select-table) 7 | 8 | 9 | https://github.com/user-attachments/assets/bb93f802-617b-4535-ba66-ab4805219d4f 10 | 11 | This plugin is an extension of the field select and allows you to open a table selection to choose elements from a relationship. 12 | 13 | ## Installation 14 | 15 | You can install the package via composer: 16 | 17 | ```bash 18 | composer require elmudo-dev/filament-select-table 19 | ``` 20 | 21 | 22 | ## Usage 23 | 24 | ```php 25 | FilamentSelectTable::make('reviewer3_id') 26 | ->live() 27 | ->label('Tests') 28 | ->multiple() // simple or multiple 29 | ->labelRelationshipAdd('label') 30 | ->titleRelationshipTable('Title') 31 | ->schema(TagsTableResource::class) 32 | ->relationship('tags', 'tag'), 33 | ``` 34 | ## Make TagsTableResource::class 35 | ```php 36 | label('id')->searchable(), 49 | TextColumn::make('tag')->label('tag')->sortable(), 50 | ]; 51 | 52 | } 53 | } 54 | ``` 55 | 56 | ## Testing 57 | 58 | ```bash 59 | composer test 60 | ``` 61 | 62 | ## Changelog 63 | 64 | Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently. 65 | 66 | ## Contributing 67 | 68 | Please see [CONTRIBUTING](.github/CONTRIBUTING.md) for details. 69 | 70 | ## Security Vulnerabilities 71 | 72 | Please review [our security policy](../../security/policy) on how to report security vulnerabilities. 73 | 74 | ## Credits 75 | 76 | - [Hernan Soto](https://github.com/elmudometal) 77 | - [All Contributors](../../contributors) 78 | 79 | ## License 80 | 81 | The MIT License (MIT). Please see [License File](LICENSE.md) for more information. 82 | -------------------------------------------------------------------------------- /src/FilamentSelectTable.php: -------------------------------------------------------------------------------- 1 | columns($this->schema::table()); 49 | } 50 | 51 | public function makeTable(): Table 52 | { 53 | return $this 54 | ->makeBaseTable() 55 | ->query($this->relationship->newQuery()) 56 | ->headerActions([ 57 | BulkAction::make('filament-select-add-relationship') 58 | ->label($this->labelRelationshipAdd) 59 | ->action(function (FilamentSelectTable $livewire, $records, Collection $selectedRecords) { 60 | $livewire->dispatch('filament-select-table', record_ids: $records->pluck('id')); 61 | $livewire->dispatch('close-modal', id: $this->componentId . '-form-component-action'); 62 | })->visible($this->isMultiple), 63 | ]) 64 | ->actions([ 65 | Action::make('add') 66 | ->label($this->labelRelationshipAdd) 67 | ->action(function (FilamentSelectTable $livewire, $record) { 68 | $livewire->dispatch('filament-select-table', record_ids: $record->id); 69 | 70 | $livewire->dispatch('close-modal', id: $this->componentId . '-form-component-action'); 71 | }) 72 | ->disabled(fn (Model $record) => $record->getKey() == $this->selectedRecords) 73 | ->visible(! $this->isMultiple), 74 | ]); 75 | } 76 | 77 | protected function getTableQuery(): Builder | Relation | null 78 | { 79 | return $this->relationship->newQuery(); 80 | } 81 | 82 | public function mountSelectTableBulkAction(string $name, ?array $selectedRecords = null): mixed 83 | { 84 | $this->mountedTableBulkAction = $name; 85 | 86 | if ($selectedRecords !== null) { 87 | $this->selectedTableRecords = $selectedRecords; 88 | } 89 | 90 | $action = $this->getMountedTableBulkAction(); 91 | 92 | if (! $action) { 93 | return null; 94 | } 95 | 96 | if ($action->isDisabled()) { 97 | return null; 98 | } 99 | 100 | $this->cacheMountedTableBulkActionForm(mountedBulkAction: $action); 101 | 102 | return null; 103 | } 104 | 105 | public function render() 106 | { 107 | return <<<'HTML' 108 |
109 | 110 | {{ $this->table }} 111 | 112 | @script 113 | 116 | @endscript 117 | 118 | @script 119 | 135 | 136 | @endscript 137 | 138 |
139 | 140 | HTML; 141 | 142 | } 143 | 144 | public function rendered() 145 | { 146 | $this->dispatch('trigger-select-records', [ 147 | 'records' => $this->selectedRecords, // The IDs of your selected rows 148 | 'livewireId' => $this->id(), // Required to link to this specific component incase you need to have multiple of the same component or multiple components supporting preselected rows 149 | ]); 150 | } 151 | } 152 | -------------------------------------------------------------------------------- /src/Forms/SelectTable.php: -------------------------------------------------------------------------------- 1 | default([]) 32 | ->native(false) 33 | ->extraAlpineAttributes([ 34 | 'x-on:filament-select-table.window' => '($event) => $wire.dispatchFormEvent(\'filament-select-table\', \'$getStatePath()\', $event.detail.record_ids)', 35 | ]); 36 | 37 | $this->afterStateHydrated(static function (SelectTable $component, $state) { 38 | if ($component->isMultiple) { 39 | if (is_array($state)) { 40 | return; 41 | } 42 | 43 | $component->state([]); 44 | } 45 | }); 46 | 47 | $this->registerListeners([ 48 | 'filament-select-table' => [ 49 | function (SelectTable $component, $statePath, array | int $records) { 50 | $component->state($records); 51 | $component->callAfterStateUpdated(); 52 | }], 53 | ]); 54 | 55 | $this->mutateDehydratedStateUsing(static function (SelectTable $component, array | int $state): array { 56 | if ($component->isMultiple) { 57 | return array_values($state); 58 | } 59 | 60 | return $state; 61 | }); 62 | 63 | } 64 | 65 | public function getCreateOptionAction(): ?Action 66 | { 67 | if ($this->isDisabled()) { 68 | return null; 69 | } 70 | 71 | $action = Action::make($this->getCreateOptionActionName()) 72 | ->modalContent( 73 | function (SelectTable $component) { 74 | $componentName = \ElmudoDev\FilamentSelectTable\FilamentSelectTable::class; 75 | 76 | return new HtmlString( 77 | Blade::render( 78 | string: "@livewire('{$componentName}', ['statePath' => \$statePath, 'ownerRecord' => \$ownerRecord, 'labelRelationshipAdd'=> \$labelRelationshipAdd, 'titleRelationshipTable'=> \$titleRelationshipTable, 'relationship' => \$relationship, 'schema' => \$schema, 'isMultiple'=>\$isMultiple, 'selectedRecords' => \$selectedRecords, 'componentId' => \$componentId])", 79 | data: [ 80 | 'statePath' => $component->getStatePath(), 81 | 'ownerRecord' => $component->getRecord(), 82 | 'labelRelationshipAdd' => $component->getLabelRelationshipAdd(), 83 | 'titleRelationshipTable' => $component->titleRelationshipTable, 84 | 'relationship' => $component->getRelationship()->getModel() ?? null, 85 | 'schema' => $component->schema, 86 | 'isMultiple' => $component->isMultiple, 87 | 'selectedRecords' => $component->getState(), 88 | 'componentId' => $component->getLivewire()->getId(), 89 | ] 90 | ) 91 | ); 92 | } 93 | ) 94 | ->modalSubmitAction(fn () => false) 95 | ->modalCancelAction(fn () => false) 96 | ->color('gray') 97 | ->icon('heroicon-m-plus') 98 | ->iconButton() 99 | ->modalHeading($this->titleRelationshipTable); 100 | 101 | if ($this->modifyManageOptionActionsUsing) { 102 | $action = $this->evaluate($this->modifyManageOptionActionsUsing, [ 103 | 'action' => $action, 104 | ]) ?? $action; 105 | } 106 | 107 | if ($this->modifyCreateOptionActionUsing) { 108 | $action = $this->evaluate($this->modifyCreateOptionActionUsing, [ 109 | 'action' => $action, 110 | ]) ?? $action; 111 | } 112 | 113 | return $action; 114 | } 115 | 116 | public function labelRelationshipAdd(string | Htmlable | Closure | null $labelRelationshipAdd): static 117 | { 118 | $this->labelRelationshipAdd = $labelRelationshipAdd; 119 | 120 | return $this; 121 | } 122 | 123 | public function titleRelationshipTable(string | Htmlable | Closure | null $titleRelationshipTable): static 124 | { 125 | $this->titleRelationshipTable = $titleRelationshipTable; 126 | 127 | return $this; 128 | } 129 | 130 | public function schema(mixed $schema): static 131 | { 132 | $this->schema = $schema; 133 | 134 | return $this; 135 | } 136 | 137 | public function getLabelRelationshipAdd(): string | Htmlable | null 138 | { 139 | if ($this->labelRelationshipAdd === null && $this->hasRelationship()) { 140 | $labelRelationshipAdd = (string) str($this->getRelationshipName()) 141 | ->before('.') 142 | ->kebab() 143 | ->replace(['-', '_'], ' ') 144 | ->ucfirst(); 145 | 146 | return $labelRelationshipAdd; 147 | } 148 | 149 | $labelRelationshipAdd = (string) str($this->labelRelationshipAdd) 150 | ->afterLast('.') 151 | ->kebab() 152 | ->replace(['-', '_'], ' ') 153 | ->ucfirst(); 154 | 155 | return $labelRelationshipAdd; 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /resources/views/index.blade.php: -------------------------------------------------------------------------------- 1 | @php 2 | use Filament\Support\Enums\Alignment; 3 | use Filament\Support\Enums\VerticalAlignment; 4 | use Filament\Support\Facades\FilamentView; 5 | use Filament\Tables\Columns\Column; 6 | use Filament\Tables\Columns\ColumnGroup; 7 | use Filament\Tables\Enums\ActionsPosition; 8 | use Filament\Tables\Enums\FiltersLayout; 9 | use Filament\Tables\Enums\RecordCheckboxPosition; 10 | use Illuminate\Support\Str; 11 | 12 | $actions = $getActions(); 13 | $flatActionsCount = count($getFlatActions()); 14 | $actionsAlignment = $getActionsAlignment(); 15 | $actionsPosition = $getActionsPosition(); 16 | $actionsColumnLabel = $getActionsColumnLabel(); 17 | $activeFiltersCount = $getActiveFiltersCount(); 18 | $columns = $getVisibleColumns(); 19 | $collapsibleColumnsLayout = $getCollapsibleColumnsLayout(); 20 | $columnsLayout = $getColumnsLayout(); 21 | $content = $getContent(); 22 | $contentGrid = $getContentGrid(); 23 | $contentFooter = $getContentFooter(); 24 | $filterIndicators = $getFilterIndicators(); 25 | $hasColumnGroups = $hasColumnGroups(); 26 | $hasColumnsLayout = $hasColumnsLayout(); 27 | $hasSummary = $hasSummary(); 28 | $header = $getHeader(); 29 | $headerActions = array_filter( 30 | $getHeaderActions(), 31 | fn (\Filament\Tables\Actions\Action | \Filament\Tables\Actions\BulkAction | \Filament\Tables\Actions\ActionGroup $action): bool => $action->isVisible(), 32 | ); 33 | $headerActionsPosition = $getHeaderActionsPosition(); 34 | $heading = $getHeading(); 35 | $group = $getGrouping(); 36 | $bulkActions = array_filter( 37 | $getBulkActions(), 38 | fn (\Filament\Tables\Actions\BulkAction | \Filament\Tables\Actions\ActionGroup $action): bool => $action->isVisible(), 39 | ); 40 | $groups = $getGroups(); 41 | $description = $getDescription(); 42 | $isGroupsOnly = $isGroupsOnly() && $group; 43 | $isReorderable = $isReorderable(); 44 | $isReordering = $isReordering(); 45 | $areGroupingSettingsVisible = (! $isReordering) && count($groups) && (! $areGroupingSettingsHidden()); 46 | $isGroupingDirectionSettingHidden = $isGroupingDirectionSettingHidden(); 47 | $isColumnSearchVisible = $isSearchableByColumn(); 48 | $isGlobalSearchVisible = $isSearchable(); 49 | $isSearchOnBlur = $isSearchOnBlur(); 50 | $isSelectionEnabled = $isSelectionEnabled() && (! $isGroupsOnly); 51 | $selectsCurrentPageOnly = $selectsCurrentPageOnly(); 52 | $recordCheckboxPosition = $getRecordCheckboxPosition(); 53 | $isStriped = $isStriped(); 54 | $isLoaded = $isLoaded(); 55 | $hasFilters = $isFilterable(); 56 | $filtersLayout = $getFiltersLayout(); 57 | $filtersTriggerAction = $getFiltersTriggerAction(); 58 | $hasFiltersDialog = $hasFilters && in_array($filtersLayout, [FiltersLayout::Dropdown, FiltersLayout::Modal]); 59 | $hasFiltersAboveContent = $hasFilters && in_array($filtersLayout, [FiltersLayout::AboveContent, FiltersLayout::AboveContentCollapsible]); 60 | $hasFiltersAboveContentCollapsible = $hasFilters && ($filtersLayout === FiltersLayout::AboveContentCollapsible); 61 | $hasFiltersBelowContent = $hasFilters && ($filtersLayout === FiltersLayout::BelowContent); 62 | $hasColumnToggleDropdown = $hasToggleableColumns(); 63 | $hasHeader = $header || $heading || $description || ($headerActions && (! $isReordering)) || $isReorderable || $areGroupingSettingsVisible || $isGlobalSearchVisible || $hasFilters || count($filterIndicators) || $hasColumnToggleDropdown; 64 | $hasHeaderToolbar = $isReorderable || $areGroupingSettingsVisible || $isGlobalSearchVisible || $hasFiltersDialog || $hasColumnToggleDropdown; 65 | $pluralModelLabel = $getPluralModelLabel(); 66 | $records = $isLoaded ? $getRecords() : null; 67 | $searchDebounce = $getSearchDebounce(); 68 | $allSelectableRecordsCount = ($isSelectionEnabled && $isLoaded) ? $getAllSelectableRecordsCount() : null; 69 | $columnsCount = count($columns); 70 | $reorderRecordsTriggerAction = $getReorderRecordsTriggerAction($isReordering); 71 | $toggleColumnsTriggerAction = $getToggleColumnsTriggerAction(); 72 | $page = $this->getTablePage(); 73 | $defaultSortOptionLabel = $getDefaultSortOptionLabel(); 74 | 75 | if (count($actions) && (! $isReordering)) { 76 | $columnsCount++; 77 | } 78 | 79 | if ($isSelectionEnabled || $isReordering) { 80 | $columnsCount++; 81 | } 82 | 83 | if ($group) { 84 | $groupedSummarySelectedState = $this->getTableSummarySelectedState($this->getAllTableSummaryQuery(), modifyQueryUsing: fn (\Illuminate\Database\Query\Builder $query) => $group->groupQuery($query, model: $getQuery()->getModel())); 85 | } 86 | 87 | $getHiddenClasses = function (Column | ColumnGroup $column): ?string { 88 | if ($breakpoint = $column->getHiddenFrom()) { 89 | return match ($breakpoint) { 90 | 'sm' => 'sm:hidden', 91 | 'md' => 'md:hidden', 92 | 'lg' => 'lg:hidden', 93 | 'xl' => 'xl:hidden', 94 | '2xl' => '2xl:hidden', 95 | }; 96 | } 97 | 98 | if ($breakpoint = $column->getVisibleFrom()) { 99 | return match ($breakpoint) { 100 | 'sm' => 'hidden sm:table-cell', 101 | 'md' => 'hidden md:table-cell', 102 | 'lg' => 'hidden lg:table-cell', 103 | 'xl' => 'hidden xl:table-cell', 104 | '2xl' => 'hidden 2xl:table-cell', 105 | }; 106 | } 107 | 108 | return null; 109 | }; 110 | @endphp 111 | 112 |
$records === null, 128 | ]) 129 | > 130 | 131 |
137 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::HEADER_BEFORE, scopes: static::class) }} 138 | 139 | @if ($header) 140 | {{ $header }} 141 | @elseif (($heading || $description || $headerActions) && ! $isReordering) 142 | 148 | @endif 149 | 150 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::HEADER_AFTER, scopes: static::class) }} 151 | 152 | @if ($hasFiltersAboveContent) 153 |
159 | 165 | 166 | @if ($hasFiltersAboveContentCollapsible) 167 | 172 | {{ $filtersTriggerAction->badge($activeFiltersCount) }} 173 | 174 | @endif 175 |
176 | @endif 177 | 178 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_BEFORE, scopes: static::class) }} 179 | 180 |
185 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_START, scopes: static::class) }} 186 | 187 |
188 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_REORDER_TRIGGER_BEFORE, scopes: static::class) }} 189 | 190 | @if ($isReorderable) 191 | 192 | {{ $reorderRecordsTriggerAction }} 193 | 194 | @endif 195 | 196 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_REORDER_TRIGGER_AFTER, scopes: static::class) }} 197 | 198 | @if ((! $isReordering) && count($bulkActions)) 199 | 204 | @endif 205 | 206 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_GROUPING_SELECTOR_BEFORE, scopes: static::class) }} 207 | 208 | @if ($areGroupingSettingsVisible) 209 | 215 | @endif 216 | 217 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_GROUPING_SELECTOR_AFTER, scopes: static::class) }} 218 |
219 | 220 | @if ($isGlobalSearchVisible || $hasFiltersDialog || $hasColumnToggleDropdown) 221 |
222 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_SEARCH_BEFORE, scopes: static::class) }} 223 | 224 | @if ($isGlobalSearchVisible) 225 | 230 | @endif 231 | 232 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_SEARCH_AFTER, scopes: static::class) }} 233 | 234 | @if ($hasFiltersDialog || $hasColumnToggleDropdown) 235 | @if ($hasFiltersDialog) 236 | 245 | @endif 246 | 247 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_TOGGLE_COLUMN_TRIGGER_BEFORE, scopes: static::class) }} 248 | 249 | @if ($hasColumnToggleDropdown) 250 | 256 | @endif 257 | 258 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_TOGGLE_COLUMN_TRIGGER_AFTER, scopes: static::class) }} 259 | @endif 260 |
261 | @endif 262 | 263 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_END) }} 264 |
265 | 266 | {{ \Filament\Support\Facades\FilamentView::renderHook(\Filament\Tables\View\TablesRenderHook::TOOLBAR_AFTER) }} 267 |
268 | 269 | @if ($isReordering) 270 | 271 | @elseif ($isSelectionEnabled && $isLoaded) 272 | 280 | @endif 281 | 282 | @if (count($filterIndicators)) 283 | 286 | @endif 287 | 288 |
! $hasHeader, 295 | ]) 296 | > 297 | @if (($content || $hasColumnsLayout) && ($records !== null) && count($records)) 298 | @if (! $isReordering) 299 | @php 300 | $sortableColumns = array_filter( 301 | $columns, 302 | fn (\Filament\Tables\Columns\Column $column): bool => $column->isSortable(), 303 | ); 304 | @endphp 305 | 306 | @if ($isSelectionEnabled || count($sortableColumns)) 307 |
310 | @if ($isSelectionEnabled && (! $isReordering)) 311 | 331 | @endif 332 | 333 | @if (count($sortableColumns)) 334 |
356 | 377 | 378 | 397 |
398 | @endif 399 |
400 | @endif 401 | @endif 402 | 403 | @if ($content) 404 | {{ $content->with(['records' => $records]) }} 405 | @else 406 | $contentGrid, 418 | 'pt-0' => $contentGrid && $this->getTableGrouping(), 419 | 'gap-y-px bg-gray-200 dark:bg-white/5' => ! $contentGrid, 420 | ]) 421 | > 422 | @php 423 | $previousRecord = null; 424 | $previousRecordGroupKey = null; 425 | $previousRecordGroupTitle = null; 426 | @endphp 427 | 428 | @foreach ($records as $record) 429 | @php 430 | $recordAction = $getRecordAction($record); 431 | $recordKey = $getRecordKey($record); 432 | $recordUrl = $getRecordUrl($record); 433 | $openRecordUrlInNewTab = $shouldOpenRecordUrlInNewTab($record); 434 | $recordGroupKey = $group?->getStringKey($record); 435 | $recordGroupTitle = $group?->getTitle($record); 436 | 437 | $collapsibleColumnsLayout?->record($record); 438 | $hasCollapsibleColumnsLayout = (bool) $collapsibleColumnsLayout?->isVisible(); 439 | @endphp 440 | 441 | @if ($recordGroupTitle !== $previousRecordGroupTitle) 442 | @if ($hasSummary && (! $isReordering) && filled($previousRecordGroupTitle)) 443 | 446 | 459 | 460 | @endif 461 | 462 | $contentGrid, 470 | ]) 471 | :x-bind:class="$hasSummary ? null : '{ \'-mb-4 border-b-0\': isGroupCollapsed(' . \Illuminate\Support\Js::from($recordGroupTitle) . ') }'" 472 | > 473 | @if ($isSelectionEnabled) 474 | 475 |
476 | 481 |
482 |
483 | @endif 484 |
485 | @endif 486 | 487 |
($recordUrl || $recordAction) && (! $contentGrid), 503 | 'hover:bg-gray-50 dark:hover:bg-white/10 dark:hover:ring-white/20' => ($recordUrl || $recordAction) && $contentGrid, 504 | 'rounded-xl shadow-sm ring-1 ring-gray-950/5 dark:bg-white/5 dark:ring-white/10' => $contentGrid, 505 | ...$getRecordClasses($record), 506 | ]) 507 | x-bind:class="{ 508 | 'hidden': 509 | {{ $group?->isCollapsible() ? 'true' : 'false' }} && 510 | isGroupCollapsed( 511 | {{ \Illuminate\Support\Js::from($recordGroupTitle) }}, 512 | ), 513 | {{ ($contentGrid ? '\'bg-gray-50 dark:bg-white/10 dark:ring-white/20\'' : '\'bg-gray-50 dark:bg-white/5 before:absolute before:start-0 before:inset-y-0 before:w-0.5 before:bg-primary-600 dark:before:bg-primary-500\'') . ': isRecordSelected(\'' . $recordKey . '\')' }}, 514 | {{ $contentGrid ? '\'bg-white dark:bg-white/5 dark:ring-white/10\': ! isRecordSelected(\'' . $recordKey . '\')' : '\'\':\'\'' }}, 515 | }" 516 | > 517 | @php 518 | $hasItemBeforeRecordContent = $isReordering || ($isSelectionEnabled && $isRecordSelectable($record)); 519 | $isRecordCollapsible = $hasCollapsibleColumnsLayout && (! $isReordering); 520 | $hasItemAfterRecordContent = $isRecordCollapsible; 521 | $recordHasActions = count($actions) && (! $isReordering); 522 | 523 | $recordContentHorizontalPaddingClasses = \Illuminate\Support\Arr::toCssClasses([ 524 | 'ps-3' => (! $contentGrid) && $hasItemBeforeRecordContent, 525 | 'ps-4 sm:ps-6' => (! $contentGrid) && (! $hasItemBeforeRecordContent), 526 | 'pe-3' => (! $contentGrid) && $hasItemAfterRecordContent, 527 | 'pe-4 sm:pe-6' => (! $contentGrid) && (! $hasItemAfterRecordContent), 528 | 'ps-2' => $contentGrid && $hasItemBeforeRecordContent, 529 | 'ps-4' => $contentGrid && (! $hasItemBeforeRecordContent), 530 | 'pe-2' => $contentGrid && $hasItemAfterRecordContent, 531 | 'pe-4' => $contentGrid && (! $hasItemAfterRecordContent), 532 | ]); 533 | 534 | $recordActionsClasses = \Illuminate\Support\Arr::toCssClasses([ 535 | 'md:ps-3' => (! $contentGrid), 536 | 'order-first' => $actionsPosition === ActionsPosition::BeforeColumns, 537 | 'ps-3' => (! $contentGrid) && $hasItemBeforeRecordContent, 538 | 'ps-4 sm:ps-6' => (! $contentGrid) && (! $hasItemBeforeRecordContent), 539 | 'pe-3' => (! $contentGrid) && $hasItemAfterRecordContent, 540 | 'pe-4 sm:pe-6' => (! $contentGrid) && (! $hasItemAfterRecordContent), 541 | 'ps-2' => $contentGrid && $hasItemBeforeRecordContent, 542 | 'ps-4' => $contentGrid && (! $hasItemBeforeRecordContent), 543 | 'pe-2' => $contentGrid && $hasItemAfterRecordContent, 544 | 'pe-4' => $contentGrid && (! $hasItemAfterRecordContent), 545 | ]); 546 | @endphp 547 | 548 |
(! $contentGrid) && $hasItemBeforeRecordContent, 552 | 'pe-1 sm:pe-3' => (! $contentGrid) && $hasItemAfterRecordContent, 553 | 'ps-1' => $contentGrid && $hasItemBeforeRecordContent, 554 | 'pe-1' => $contentGrid && $hasItemAfterRecordContent, 555 | ]) 556 | > 557 | @if ($isReordering) 558 | 561 | @elseif ($isSelectionEnabled && $isRecordSelectable($record)) 562 | 569 | @endif 570 | 571 | @php 572 | $recordContentClasses = \Illuminate\Support\Arr::toCssClasses([ 573 | $recordContentHorizontalPaddingClasses, 574 | 'block w-full', 575 | ]); 576 | @endphp 577 | 578 |
! $contentGrid, 582 | ]) 583 | > 584 |
585 | @if ($recordUrl) 586 | 590 | 596 | 597 | @elseif ($recordAction) 598 | @php 599 | $recordWireClickAction = $getAction($recordAction) 600 | ? "mountTableAction('{$recordAction}', '{$recordKey}')" 601 | : $recordWireClickAction = "{$recordAction}('{$recordKey}')"; 602 | @endphp 603 | 604 | 618 | @else 619 |
622 | 628 |
629 | @endif 630 | 631 | @if ($hasCollapsibleColumnsLayout && (! $isReordering)) 632 |
637 | {{ $collapsibleColumnsLayout->viewData(['recordKey' => $recordKey]) }} 638 |
639 | @endif 640 |
641 | 642 | @if ($recordHasActions) 643 | 650 | @endif 651 |
652 | 653 | @if ($isRecordCollapsible) 654 | 662 | @endif 663 |
664 |
665 | 666 | @php 667 | $previousRecordGroupKey = $recordGroupKey; 668 | $previousRecordGroupTitle = $recordGroupTitle; 669 | $previousRecord = $record; 670 | @endphp 671 | @endforeach 672 | 673 | @if ($hasSummary && (! $isReordering) && filled($previousRecordGroupTitle) && ((! $records instanceof \Illuminate\Contracts\Pagination\Paginator) || (! $records->hasMorePages()))) 674 | 675 | 683 | 684 | @endif 685 |
686 | @endif 687 | 688 | @if (($content || $hasColumnsLayout) && $contentFooter) 689 | {{ 690 | $contentFooter->with([ 691 | 'columns' => $columns, 692 | 'records' => $records, 693 | ]) 694 | }} 695 | @endif 696 | 697 | @if ($hasSummary && (! $isReordering)) 698 | 699 | 706 | 707 | @endif 708 | @elseif (($records !== null) && count($records)) 709 | 713 | @if ($hasColumnGroups) 714 | 715 | @if ($isReordering) 716 | 717 | @else 718 | @if (count($actions) && in_array($actionsPosition, [ActionsPosition::BeforeCells, ActionsPosition::BeforeColumns])) 719 | 720 | @endif 721 | 722 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::BeforeCells) 723 | 724 | @endif 725 | @endif 726 | 727 | @foreach ($columnsLayout as $columnGroup) 728 | @if ($columnGroup instanceof Column) 729 | @if ($columnGroup->isVisible() && (! $columnGroup->isToggledHidden())) 730 | 731 | @endif 732 | @elseif ($columnGroup instanceof ColumnGroup) 733 | @php 734 | $columnGroupAlignment = $columnGroup->getAlignment(); 735 | $columnGroupColumnsCount = count($columnGroup->getVisibleColumns()); 736 | $isColumnGroupHeaderWrapped = $columnGroup->isHeaderWrapped(); 737 | @endphp 738 | 739 | @if ($columnGroupColumnsCount) 740 | getExtraHeaderAttributeBag()->class([ 744 | 'fi-table-header-group-cell border-gray-200 px-3 py-2 dark:border-white/5 sm:first-of-type:ps-6 sm:last-of-type:pe-6 [&:not(:first-of-type)]:border-s [&:not(:last-of-type)]:border-e', 745 | ]) 746 | }} 747 | > 748 |
! $isColumnGroupHeaderWrapped, 752 | 'whitespace-normal' => $isColumnGroupHeaderWrapped, 753 | match ($columnGroupAlignment) { 754 | Alignment::Start => 'justify-start', 755 | Alignment::Center => 'justify-center', 756 | Alignment::End => 'justify-end', 757 | Alignment::Left => 'justify-start rtl:flex-row-reverse', 758 | Alignment::Right => 'justify-end rtl:flex-row-reverse', 759 | Alignment::Justify, Alignment::Between => 'justify-between', 760 | default => $columnGroupAlignment, 761 | }, 762 | $getHiddenClasses($columnGroup), 763 | ]) 764 | > 765 | 768 | {{ $columnGroup->getLabel() }} 769 | 770 |
771 | 772 | @endif 773 | @endif 774 | @endforeach 775 | 776 | @if (! $isReordering) 777 | @if (count($actions) && in_array($actionsPosition, [ActionsPosition::AfterColumns, ActionsPosition::AfterCells])) 778 | 779 | @endif 780 | 781 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::AfterCells) 782 | 783 | @endif 784 | @endif 785 |
786 | @endif 787 | 788 | 789 | @if ($isReordering) 790 | 791 | @else 792 | @if (count($actions) && $actionsPosition === ActionsPosition::BeforeCells) 793 | @if ($actionsColumnLabel) 794 | 795 | {{ $actionsColumnLabel }} 796 | 797 | @else 798 | 802 | @endif 803 | @endif 804 | 805 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::BeforeCells) 806 | 807 | 827 | 828 | @endif 829 | 830 | @if (count($actions) && $actionsPosition === ActionsPosition::BeforeColumns) 831 | @if ($actionsColumnLabel) 832 | 833 | {{ $actionsColumnLabel }} 834 | 835 | @else 836 | 840 | @endif 841 | @endif 842 | @endif 843 | 844 | @foreach ($columns as $column) 845 | @php 846 | $columnWidth = $column->getWidth(); 847 | @endphp 848 | 849 | 868 | {{ $column->getLabel() }} 869 | 870 | @endforeach 871 | 872 | @if (! $isReordering) 873 | @if (count($actions) && $actionsPosition === ActionsPosition::AfterColumns) 874 | @if ($actionsColumnLabel) 875 | 878 | {{ $actionsColumnLabel }} 879 | 880 | @else 881 | 885 | @endif 886 | @endif 887 | 888 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::AfterCells) 889 | 890 | 910 | 911 | @endif 912 | 913 | @if (count($actions) && $actionsPosition === ActionsPosition::AfterCells) 914 | @if ($actionsColumnLabel) 915 | 918 | {{ $actionsColumnLabel }} 919 | 920 | @else 921 | 925 | @endif 926 | @endif 927 | @endif 928 | 929 | 930 | @if ($isColumnSearchVisible) 931 | 932 | @if ($isReordering) 933 | 934 | @else 935 | @if (count($actions) && in_array($actionsPosition, [ActionsPosition::BeforeCells, ActionsPosition::BeforeColumns])) 936 | 937 | @endif 938 | 939 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::BeforeCells) 940 | 941 | @endif 942 | @endif 943 | 944 | @foreach ($columns as $column) 945 | getName())->camel()->kebab(), 948 | 'px-3 py-2', 949 | ]) 950 | > 951 | @if ($column->isIndividuallySearchable()) 952 | 957 | @endif 958 | 959 | @endforeach 960 | 961 | @if (! $isReordering) 962 | @if (count($actions) && in_array($actionsPosition, [ActionsPosition::AfterColumns, ActionsPosition::AfterCells])) 963 | 964 | @endif 965 | 966 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::AfterCells) 967 | 968 | @endif 969 | @endif 970 | 971 | @endif 972 | 973 | @if (($records !== null) && count($records)) 974 | @php 975 | $isRecordRowStriped = false; 976 | $previousRecord = null; 977 | $previousRecordGroupKey = null; 978 | $previousRecordGroupTitle = null; 979 | @endphp 980 | 981 | @foreach ($records as $record) 982 | @php 983 | $recordAction = $getRecordAction($record); 984 | $recordKey = $getRecordKey($record); 985 | $recordUrl = $getRecordUrl($record); 986 | $openRecordUrlInNewTab = $shouldOpenRecordUrlInNewTab($record); 987 | $recordGroupKey = $group?->getStringKey($record); 988 | $recordGroupTitle = $group?->getTitle($record); 989 | @endphp 990 | 991 | @if ($recordGroupTitle !== $previousRecordGroupTitle) 992 | @if ($hasSummary && (! $isReordering) && filled($previousRecordGroupTitle)) 993 | 1005 | @endif 1006 | 1007 | @if (! $isGroupsOnly) 1008 | 1009 | @php 1010 | $groupHeaderColspan = $columnsCount; 1011 | 1012 | if ($isSelectionEnabled) { 1013 | $groupHeaderColspan--; 1014 | 1015 | if ( 1016 | ($recordCheckboxPosition === RecordCheckboxPosition::BeforeCells) && 1017 | count($actions) && 1018 | ($actionsPosition === ActionsPosition::BeforeCells) 1019 | ) { 1020 | $groupHeaderColspan--; 1021 | } 1022 | } 1023 | @endphp 1024 | 1025 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::BeforeCells) 1026 | @if (count($actions) && $actionsPosition === ActionsPosition::BeforeCells) 1027 | 1030 | @endif 1031 | 1032 | 1033 | 1038 | 1039 | @endif 1040 | 1041 | 1045 | 1051 | 1052 | 1053 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::AfterCells) 1054 | 1055 | 1060 | 1061 | @endif 1062 | 1063 | @endif 1064 | 1065 | @php 1066 | $isRecordRowStriped = false; 1067 | @endphp 1068 | @endif 1069 | 1070 | @if (! $isGroupsOnly) 1071 | $isReordering, 1082 | ...$getRecordClasses($record), 1083 | ]) 1084 | > 1085 | @if ($isReordering) 1086 | 1087 | 1088 | 1089 | @endif 1090 | 1091 | @if (count($actions) && $actionsPosition === ActionsPosition::BeforeCells && (! $isReordering)) 1092 | 1093 | 1098 | 1099 | @endif 1100 | 1101 | @if ($isSelectionEnabled && ($recordCheckboxPosition === RecordCheckboxPosition::BeforeCells) && (! $isReordering)) 1102 | 1103 | @if ($isRecordSelectable($record)) 1104 | 1111 | @endif 1112 | 1113 | @endif 1114 | 1115 | @if (count($actions) && $actionsPosition === ActionsPosition::BeforeColumns && (! $isReordering)) 1116 | 1117 | 1122 | 1123 | @endif 1124 | 1125 | @foreach ($columns as $column) 1126 | @php 1127 | $column->record($record); 1128 | $column->rowLoop($loop->parent); 1129 | @endphp 1130 | 1131 | 1147 | 1156 | 1157 | @endforeach 1158 | 1159 | @if (count($actions) && $actionsPosition === ActionsPosition::AfterColumns && (! $isReordering)) 1160 | 1161 | 1166 | 1167 | @endif 1168 | 1169 | @if ($isSelectionEnabled && $recordCheckboxPosition === RecordCheckboxPosition::AfterCells && (! $isReordering)) 1170 | 1171 | @if ($isRecordSelectable($record)) 1172 | 1179 | @endif 1180 | 1181 | @endif 1182 | 1183 | @if (count($actions) && $actionsPosition === ActionsPosition::AfterCells) 1184 | $isReordering, 1187 | ]) 1188 | > 1189 | 1194 | 1195 | @endif 1196 | 1197 | @endif 1198 | 1199 | @php 1200 | $isRecordRowStriped = ! $isRecordRowStriped; 1201 | $previousRecord = $record; 1202 | $previousRecordGroupKey = $recordGroupKey; 1203 | $previousRecordGroupTitle = $recordGroupTitle; 1204 | @endphp 1205 | @endforeach 1206 | 1207 | @if ($hasSummary && (! $isReordering) && filled($previousRecordGroupTitle) && ((! $records instanceof \Illuminate\Contracts\Pagination\Paginator) || (! $records->hasMorePages()))) 1208 | 1220 | @endif 1221 | 1222 | @if ($hasSummary && (! $isReordering)) 1223 | 1234 | @endif 1235 | 1236 | @if ($contentFooter) 1237 | 1238 | {{ 1239 | $contentFooter->with([ 1240 | 'columns' => $columns, 1241 | 'records' => $records, 1242 | ]) 1243 | }} 1244 | 1245 | @endif 1246 | @endif 1247 |
1248 | @elseif ($records === null) 1249 |
1250 | @elseif ($emptyState = $getEmptyState()) 1251 | {{ $emptyState }} 1252 | @else 1253 | 1254 | 1255 | 1261 | 1262 | 1263 | @endif 1264 |
1265 | 1266 | @if ((($records instanceof \Illuminate\Contracts\Pagination\Paginator) || ($records instanceof \Illuminate\Contracts\Pagination\CursorPaginator)) && 1267 | ((! ($records instanceof \Illuminate\Contracts\Pagination\LengthAwarePaginator)) || $records->total())) 1268 | 1274 | @endif 1275 | 1276 | @if ($hasFiltersBelowContent) 1277 | 1282 | @endif 1283 |
1284 | 1285 | 1286 |
1287 | --------------------------------------------------------------------------------