diff --git a/resources/views/bootstrap-4/components/table/row.blade.php b/resources/views/bootstrap-4/components/table/row.blade.php index 6a0f27458..9fa710eee 100644 --- a/resources/views/bootstrap-4/components/table/row.blade.php +++ b/resources/views/bootstrap-4/components/table/row.blade.php @@ -1,6 +1,6 @@ @props(['url' => null, 'target' => '_self', 'reordering' => false, 'customAttributes' => []]) -@if (!$reordering && $attributes->has('wire:sortable.item')) +@if (!$reordering && (method_exists($attributes, 'has') ? $attributes->has('wire:sortable.item') : array_key_exists('wire:sortable.item', $attributes->getAttributes()))) @php $attributes = $attributes->filter(fn ($value, $key) => $key !== 'wire:sortable.item'); @endphp diff --git a/resources/views/bootstrap-4/includes/filter-pills.blade.php b/resources/views/bootstrap-4/includes/filter-pills.blade.php index 4e748b4a4..020ad9775 100644 --- a/resources/views/bootstrap-4/includes/filter-pills.blade.php +++ b/resources/views/bootstrap-4/includes/filter-pills.blade.php @@ -9,7 +9,7 @@ wire:key="filter-pill-{{ $key }}" class="badge badge-pill badge-info d-inline-flex align-items-center" > - {{ $filterNames[$key] ?? collect($this->columns())->pluck('text', 'column')->get($key, ucwords(strtr($key, ['_' => ' ', '-' => ' ']))) }}: + {{ $filterNames[$key] ?? collect($this->columns())->pluck('text', 'column')->get($key, isset($customFilters[$key]) && property_exists($customFilters[$key], 'name') ? $customFilters[$key]->name : ucwords(strtr($key, ['_' => ' ', '-' => ' ']))) }}: @if(isset($customFilters[$key]) && method_exists($customFilters[$key], 'options')) @if(is_array($value)) @foreach($value as $selectedValue) diff --git a/resources/views/bootstrap-5/components/table/row.blade.php b/resources/views/bootstrap-5/components/table/row.blade.php index 6a0f27458..9fa710eee 100644 --- a/resources/views/bootstrap-5/components/table/row.blade.php +++ b/resources/views/bootstrap-5/components/table/row.blade.php @@ -1,6 +1,6 @@ @props(['url' => null, 'target' => '_self', 'reordering' => false, 'customAttributes' => []]) -@if (!$reordering && $attributes->has('wire:sortable.item')) +@if (!$reordering && (method_exists($attributes, 'has') ? $attributes->has('wire:sortable.item') : array_key_exists('wire:sortable.item', $attributes->getAttributes()))) @php $attributes = $attributes->filter(fn ($value, $key) => $key !== 'wire:sortable.item'); @endphp diff --git a/resources/views/bootstrap-5/includes/filter-pills.blade.php b/resources/views/bootstrap-5/includes/filter-pills.blade.php index 6c8c30ea3..dc4cf08d7 100644 --- a/resources/views/bootstrap-5/includes/filter-pills.blade.php +++ b/resources/views/bootstrap-5/includes/filter-pills.blade.php @@ -9,7 +9,7 @@ wire:key="filter-pill-{{ $key }}" class="badge rounded-pill bg-info d-inline-flex align-items-center" > - {{ $filterNames[$key] ?? collect($this->columns())->pluck('text', 'column')->get($key, ucwords(strtr($key, ['_' => ' ', '-' => ' ']))) }}: + {{ $filterNames[$key] ?? collect($this->columns())->pluck('text', 'column')->get($key, isset($customFilters[$key]) && property_exists($customFilters[$key], 'name') ? $customFilters[$key]->name : ucwords(strtr($key, ['_' => ' ', '-' => ' ']))) }}: @if(isset($customFilters[$key]) && method_exists($customFilters[$key], 'options')) @if(is_array($value)) @foreach($value as $selectedValue) diff --git a/resources/views/tailwind/components/table/row.blade.php b/resources/views/tailwind/components/table/row.blade.php index c6cf88265..f22f7e99d 100644 --- a/resources/views/tailwind/components/table/row.blade.php +++ b/resources/views/tailwind/components/table/row.blade.php @@ -1,13 +1,13 @@ @props(['url' => null, 'target' => '_self', 'reordering' => false, 'customAttributes' => []]) -@if (!$reordering && $attributes->has('wire:sortable.item')) +@if (!$reordering && (method_exists($attributes, 'has') ? $attributes->has('wire:sortable.item') : array_key_exists('wire:sortable.item', $attributes->getAttributes()))) @php $attributes = $attributes->filter(fn ($value, $key) => $key !== 'wire:sortable.item'); @endphp @endif merge($customAttributes)->class(['cursor-pointer' => $url]) }} + {{ $attributes->merge($customAttributes)->merge(['class' => $url ? 'cursor-pointer' : '']) }} @if ($url) onclick="window.open('{{ $url }}', '{{ $target }}')" diff --git a/resources/views/tailwind/includes/filter-pills.blade.php b/resources/views/tailwind/includes/filter-pills.blade.php index 2491d9437..3919030b2 100644 --- a/resources/views/tailwind/includes/filter-pills.blade.php +++ b/resources/views/tailwind/includes/filter-pills.blade.php @@ -9,7 +9,7 @@ wire:key="filter-pill-{{ $key }}" class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium leading-4 bg-indigo-100 text-indigo-800 capitalize dark:bg-indigo-200 dark:text-indigo-900" > - {{ $filterNames[$key] ?? collect($this->columns())->pluck('text', 'column')->get($key, ucwords(strtr($key, ['_' => ' ', '-' => ' ']))) }}: + {{ $filterNames[$key] ?? collect($this->columns())->pluck('text', 'column')->get($key, isset($customFilters[$key]) && property_exists($customFilters[$key], 'name') ? $customFilters[$key]->name : ucwords(strtr($key, ['_' => ' ', '-' => ' ']))) }}: @if(isset($customFilters[$key]) && method_exists($customFilters[$key], 'options')) @if(is_array($value)) @foreach($value as $selectedValue) diff --git a/tests/DataTableComponentTest.php b/tests/DataTableComponentTest.php index 470d6875d..4dfca67b3 100644 --- a/tests/DataTableComponentTest.php +++ b/tests/DataTableComponentTest.php @@ -3,7 +3,9 @@ namespace Rappasoft\LaravelLivewireTables\Tests; use Illuminate\Contracts\Pagination\LengthAwarePaginator; +use Illuminate\Encryption\Encrypter; use Illuminate\Support\Collection; +use Livewire\Livewire; use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\Tests\Http\Livewire\PetsAltQueryTable; use Rappasoft\LaravelLivewireTables\Tests\Http\Livewire\PetsTable; @@ -115,6 +117,42 @@ public function search_filter_alt_query_relation() $this->assertEquals(2, $this->tableAltQuery->rows->total()); } + /** @test */ + public function custom_filter() + { + $this->table->filters['species.name'] = 1; + + $this->assertTrue($this->table->getRowsProperty()->where('name', 'Cartman')->isNotEmpty()); + $this->assertTrue($this->table->getRowsProperty()->where('name', 'Tux')->isNotEmpty()); + $this->assertFalse($this->table->getRowsProperty()->where('May', 'Tux')->isNotEmpty()); + $this->assertFalse($this->table->getRowsProperty()->where('Ben', 'Tux')->isNotEmpty()); + $this->assertFalse($this->table->getRowsProperty()->where('Chico', 'Tux')->isNotEmpty()); + } + + /** @test */ + public function custom_filters_pills_label_use_column_name_when_possible() + { + config()->set('app.key', Encrypter::generateKey(config('app.cipher'))); + + Livewire::test(PetsTable::class) + ->set('filters', [ + 'species.name' => 1, + ]) + ->assertSeeTextInOrder(['Applied Filters:', 'Species:', 'Cat', 'Filters']); + } + + /** @test */ + public function custom_filters_pills_label_use_filter_name_when_is_not_bound_to_a_column() + { + config()->set('app.key', Encrypter::generateKey(config('app.cipher'))); + + Livewire::test(PetsTable::class) + ->set('filters', [ + 'breed_id' => 1, + ]) + ->assertSeeTextInOrder(['Applied Filters:', 'Filter Breed:', 'American Shorthair', 'Filters']); + } + /** @test */ public function bulk_actions_defined_through_function() { diff --git a/tests/Http/Livewire/PetsTable.php b/tests/Http/Livewire/PetsTable.php index 707290505..564494475 100644 --- a/tests/Http/Livewire/PetsTable.php +++ b/tests/Http/Livewire/PetsTable.php @@ -6,9 +6,30 @@ use Rappasoft\LaravelLivewireTables\DataTableComponent; use Rappasoft\LaravelLivewireTables\Tests\Models\Pet; use Rappasoft\LaravelLivewireTables\Views\Column; +use Rappasoft\LaravelLivewireTables\Views\Filter; class PetsTable extends DataTableComponent { + public function filters(): array + { + return [ + 'species.name' => Filter::make('Filter Species')->select([ + '' => 'All', + 1 => 'Cat', + 2 => 'Dog', + 3 => 'Horse', + 4 => 'Bird', + ]), + 'breed_id' => Filter::make('Filter Breed')->select([ + '' => 'All', + 1 => 'American Shorthair', + 2 => 'Maine Coon', + 3 => 'Persian', + 4 => 'Norwegian Forest', + ]), + ]; + } + public function bulkActions(): array { return ['count' => 'Count selected']; @@ -17,11 +38,13 @@ public function bulkActions(): array /** * @return Builder */ - public function query() : Builder + public function query(): Builder { return Pet::query() ->with('species') - ->with('breed'); + ->with('breed') + ->when($this->getFilter('species.name'), fn (Builder $query, $specimen_id) => $query->where('species_id', $specimen_id)) + ->when($this->getFilter('breed_id'), fn (Builder $query, $breed_id) => $query->where('breed_id', $breed_id)); } public function columns(): array