Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Laravel Livewire Tables Demo Table Source
<?php
namespace App\Http\Livewire;
use App\Models\Tag;
use App\Models\User;
use Rappasoft\LaravelLivewireTables\DataTableComponent;
use Rappasoft\LaravelLivewireTables\Views\Column;
use Rappasoft\LaravelLivewireTables\Views\Filter;
class UsersTable extends DataTableComponent
{
public bool $dumpFilters = false;
public bool $columnSelect = true;
public string $defaultSortColumn = 'sort';
public bool $reorderEnabled = true;
public array $bulkActions = [
'activate' => 'Activate',
'deactivate' => 'Deactivate',
];
public $columnSearch = [
'name' => null,
'email' => null,
];
public function boot()
{
$this->queryString['columnSearch'] = ['except' => null];
}
public function columns(): array
{
return [
Column::make('Sort')
->sortable()
->footer(function($rows) {
return 'Sum: ' . $rows->sum('sort');
}),
Column::make('Name')
->sortable()
->searchable()
->asHtml()
->secondaryHeader(function() {
return view('tables.cells.input-search', ['field' => 'name', 'columnSearch' => $this->columnSearch]);
}),
Column::make('E-mail', 'email')
->sortable()
->searchable()
->asHtml()
->secondaryHeader(function() {
return view('tables.cells.input-search', ['field' => 'email', 'columnSearch' => $this->columnSearch]);
}),
Column::make('Active')
->sortable()
->format(function ($value) {
return view('tables.cells.boolean',
[
'boolean' => $value
]
);
}),
Column::make('Tags')
->format(function($value, $column, $user) {
return $user->tags()->pluck('name')->implode('<br/>');
})
->asHtml(),
Column::make('Verified', 'email_verified_at')
->sortable()
->excludeFromSelectable(),
];
}
public function filters(): array
{
return [
'verified' => Filter::make('E-mail Verified')
->select([
'' => 'Any',
'yes' => 'Yes',
'no' => 'No',
]),
'active' => Filter::make('Active')
->select([
'' => 'Any',
'yes' => 'Yes',
'no' => 'No',
]),
'tags' => Filter::make('Tags')
->multiSelect(
Tag::query()
->orderBy('name')
->get()
->keyBy('id')
->map(fn($tag) => $tag->name)
->toArray()
),
'verified_from' => Filter::make('Verified From')
->date(),
'verified_to' => Filter::make('Verified To')
->date(),
];
}
public function query()
{
return User::with('tags')
->when($this->getFilter('verified'), function ($query, $verified) {
if ($verified === 'yes') {
return $query->whereNotNull('verified');
}
return $query->whereNull('verified');
})
->when($this->getFilter('active'), fn($query, $active) => $query->where('active', $active === 'yes'))
->when($this->getFilter('verified_from'), fn($query, $date) => $query->where('email_verified_at', '>=', $date))
->when($this->getFilter('verified_to'), fn($query, $date) => $query->where('email_verified_at', '<=', $date))
->when($this->getFilter('tags'), fn($query, $tags) => $query->whereHas('tags', fn($query) => $query->whereIn('tags.id', $tags)))
->when($this->columnSearch['name'] ?? null, fn ($query, $name) => $query->where('name', 'like', '%' . $name . '%'))
->when($this->columnSearch['email'] ?? null, fn ($query, $email) => $query->where('email', 'like', '%' . $email . '%'));
}
public function reorder($items): void
{
foreach ($items as $item) {
optional(User::find((int)$item['value']))->update(['sort' => (int)$item['order']]);
}
}
public function activate(): void
{
if ($this->selectedRowsQuery->count() > 0) {
User::whereIn('id', $this->selectedKeys())->update(['active' => true]);
}
$this->selected = [];
$this->resetBulk();
}
public function deactivate(): void
{
if ($this->selectedRowsQuery->count() > 0) {
User::whereIn('id', $this->selectedKeys())->update(['active' => false]);
}
$this->resetBulk();
}
public function setTableRowClass($row): ?string
{
if ($row->active === false) {
if (config('livewire-tables.theme') === 'tailwind') {
return '!bg-red-200';
} else if (config('livewire-tables.theme') === 'bootstrap-4') {
return 'bg-danger text-white';
} else if(config('livewire-tables.theme') === 'bootstrap-5') {
return 'bg-danger text-white';
}
}
return null;
}
public function getTableRowUrl(): string
{
return 'https://rappasoft.com';
}
public function getTableRowUrlTarget(): string
{
return '_blank';
}
}
// input-search.blade.php
@if (config('livewire-tables.theme') === 'tailwind')
<div class="flex rounded-md shadow-sm">
<input
wire:model.debounce="columnSearch.{{ $field }}"
placeholder="Search {{ ucfirst($field) }}"
type="text"
class="block w-full border-gray-300 rounded-md shadow-sm transition duration-150 ease-in-out sm:text-sm sm:leading-5 dark:bg-gray-700 dark:text-white dark:border-gray-600 @if (isset($columnSearch[$field]) && strlen($columnSearch[$field])) rounded-none rounded-l-md focus:ring-0 focus:border-gray-300 @else focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50 rounded-md @endif"
/>
@if (isset($columnSearch[$field]) && strlen($columnSearch[$field]))
<span wire:click="$set('columnSearch.{{ $field }}', null)" class="inline-flex items-center px-3 text-gray-500 bg-gray-50 rounded-r-md border border-l-0 border-gray-300 cursor-pointer sm:text-sm dark:bg-gray-700 dark:text-white dark:border-gray-600 dark:hover:bg-gray-600">
<svg xmlns="http://www.w3.org/2000/svg" class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</span>
@endif
</div>
@endif
@if (config('livewire-tables.theme') === 'bootstrap-4')
<div class="mb-3 mb-md-0 input-group">
<input
wire:model.debounce="columnSearch.{{ $field }}"
placeholder="Search {{ ucfirst($field) }}"
type="text"
class="form-control"
>
@if (isset($columnSearch[$field]) && strlen($columnSearch[$field]))
<div class="input-group-append">
<button wire:click="$set('columnSearch.{{ $field }}', null)" class="btn btn-outline-secondary" type="button">
<svg style="width:.75em;height:.75em" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
@endif
</div>
@endif
@if (config('livewire-tables.theme') === 'bootstrap-5')
<div class="mb-3 mb-md-0 input-group">
<input
wire:model.debounce="columnSearch.{{ $field }}"
placeholder="Search {{ ucfirst($field) }}"
type="text"
class="form-control"
>
@if (isset($columnSearch[$field]) && strlen($columnSearch[$field]))
<button wire:click="$set('columnSearch.{{ $field }}', null)" class="btn btn-outline-secondary" type="button">
<svg style="width:.75em;height:.75em" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
@endif
</div>
@endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment