diff options
author | Sam Light <samlight1994@gmail.com> | 2023-11-06 00:06:39 +0000 |
---|---|---|
committer | Sam Light <samlight1994@gmail.com> | 2023-11-06 00:06:39 +0000 |
commit | 8f69cb7f3df70c40cbae47a5661dc9ae67aae728 (patch) | |
tree | 8ce246d53dc428c1fe95fad04e631a89048ddea0 | |
parent | 5c24746657ac23c7a65c4e4efc89cf6bfcb5a52c (diff) |
Lots of table improvments
-rw-r--r-- | resources/views/table.blade.php | 36 | ||||
-rw-r--r-- | src/Columns/Column.php | 55 | ||||
-rw-r--r-- | src/TableComponent.php | 65 |
3 files changed, 129 insertions, 27 deletions
diff --git a/resources/views/table.blade.php b/resources/views/table.blade.php index 1938b48..5f6df75 100644 --- a/resources/views/table.blade.php +++ b/resources/views/table.blade.php @@ -1,4 +1,40 @@ <div> + <div class="table-controls pb-2 d-flex justify-content-between align-items-center"> + @if($searchable) + <div> + <input class="form-control border-secondary" type="search" + wire:model.live.debounce.{{ $searchDebounce}}="search" + placeholder="{{ __('Search') }}..." /> + </div> + @endif + <div class="d-flex gap-3"> + @if($showColumnSelect) + <div class="dropdown"> + <button type="button" class="btn btn-outline-secondary border-secondary" + data-bs-toggle="dropdown" aria-expanded="false" + data-bs-auto-close="outside"> + {{ __('Columns') }} + </button> + <div class="dropdown-menu p-4"> + @foreach($allColumns->filter(fn($c) => $c->getShowInSelect()) as $column) + <label class="d-block"> + <input type="checkbox" wire:model.live="activeColumns" + value="{{ $column->name }}" /> + {{ $column->title }} + </label> + @endforeach + </div> + </div> + @endif + @if($showPageSizeSelect) + <select wire:model.live="pageSize" class="form-select border-secondary"> + @foreach($pageSizes as $size) + <option value="{{ $size }}">{{ $size }}</option> + @endforeach + </select> + @endif + </div> + </div> <table class="table"> <thead> <tr> diff --git a/src/Columns/Column.php b/src/Columns/Column.php index 7b9f248..f3fe811 100644 --- a/src/Columns/Column.php +++ b/src/Columns/Column.php @@ -2,40 +2,48 @@ namespace Lightscale\LaralightTables\Columns; +use Lightscale\LaralightTables\TableComponent; + use Illuminate\Database\Eloquent\Model; use Illuminate\View\ComponentAttributeBag; +use Illuminate\Support\HtmlString; use Closure; class Column { private TableComponent $table; + private bool $showInSelect; - private Closure $displayFn; + private ?Closure $slotFn = null; private ?Closure $sortFn = null; - private ?Closure $searchFn = null; - private ?Closure $attributesFn = null; + private ?Closure $tdAttributesFn = null; public function __construct( public string $name, - public string $title + public ?string $title = null ) { - $this->displayFn = Closure::fromCallable([$this, 'defaultDisplay']); + $this->showInSelect = $this->title !== null; } - public static function make(string $name, $title) : static + public static function make(string $name, ?string $title = null) : static { return new static($name, $title); } - private function defaultDisplay(Model $row, Column $column) + public function setTable(TableComponent $table) : void + { + $this->table = $table; + } + + private function defaultSlot(Model $row) { - return $row->{$column->name}; + return $row->{$this->name}; } - public function display(callable $fn) : static + public function slot(callable $fn) : static { - $this->displayFn = Closure::fromCallable($fn); + $this->slotFn = Closure::fromCallable($fn); return $this; } @@ -45,24 +53,33 @@ class Column { return $this; } - public function searchable(callable $fn) : static + public function tdAttributes(callable $fn) : static { - $this->searchFn = Closure::fromCallable($fn); + $this->tdAttributesFn = Closure::fromCallable($fn); return $this; } - public function attributes(callable $fn) : static + public function showInSelect($show = true) { - $this->attributesFn = Closure::fromCallable($fn); - return $this; + $this->showInSelect = $show; + } + + public function getShowInSelect() + { + return $this->showInSelect; + } + + protected function getContent(Model $row) + { + return $this->slotFn?->call($this, $row, $this) ?? $this->defaultSlot($row); } public function view(Model $row) { - $attributes = $this->attributesFn?->call($this, $row) ?? []; - $attributes = new ComponentAttributeBag($attributes); - $content = $this->displayFn->call($this, $row, $this); - return view('laralight-tables::column', compact('attributes', 'content')); + $attributes = $this->tdAttributesFn?->call($this, $row) ?? []; + $attributes = (new ComponentAttributeBag($attributes))->toHtml(); + $content = $this->getContent($row); + return new HtmlString("<td {$attributes}>{$content}</td>"); } } diff --git a/src/TableComponent.php b/src/TableComponent.php index e530415..04d457e 100644 --- a/src/TableComponent.php +++ b/src/TableComponent.php @@ -6,7 +6,7 @@ use Livewire\Component; use Livewire\WithPagination; use Illuminate\Database\Eloquent\Builder; -use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Str; use Exception; @@ -14,10 +14,34 @@ abstract class TableComponent extends Component { use WithPagination; + // Config protected $paginationTheme = 'bootstrap'; protected bool $searchable = true; + protected int $searchMinLength = 2; + protected int $searchDebounce = 250; + protected bool $showPageSizeSelect = true; + protected bool $showColumnSelect = true; - protected Model $model = null; + protected array $pageSizes = [10, 25, 50]; + + protected $model = null; + + // Properties + public string $search = ''; + public int $pageSize = 0; + public array $activeColumns = []; + + public function __construct() + { + $this->pageSize = $this->pageSizes[0] ?? 0; + } + + public function mount() + { + foreach($this->getColumns() as $column) { + $this->activeColumns[] = $column->name; + } + } protected function query() : Builder { @@ -37,19 +61,44 @@ abstract class TableComponent extends Component return []; } - protected buildQuery() : Builder + protected function buildQuery() : Builder { $query = $this->query(); + + if($this->searchable && (Str::length($this->search) >= $this->searchMinLength)) { + $this->search($query, $this->search); + } + + return $query; + } + + protected function getColumns() + { + static $columns = null; + + if($columns === null) { + $columns = collect($this->columns())->each( + fn($c) => $c->setTable($this) + ); + } + + return $columns; } public function render() { - $this->buildQuery()->paginate(); - $data = $query->paginate($this->pageSize); - $columns = $this->columns(); + $data = $this->buildQuery()->paginate($this->pageSize); + $allColumns = $this->getColumns(); + $columns = $allColumns->filter(fn($c) => in_array($c->name,$this->activeColumns)); - return view('laralight-tables::table', compact( - 'data', 'columns' + return view('laralight-tables::table', [ + 'searchable' => $this->searchable, + 'searchDebounce' => $this->searchDebounce, + 'showPageSizeSelect' => $this->showPageSizeSelect, + 'showColumnSelect' => $this->showColumnSelect, + 'pageSizes' => $this->pageSizes, + ] + compact( + 'data', 'allColumns', 'columns' )); } } |