PHP code example of salioudiabate / livewire-datatable

1. Go to this page and download the library: Download salioudiabate/livewire-datatable library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

salioudiabate / livewire-datatable example snippets


class UsersTable extends DataTableComponent
{
    public function builder(): Builder
    {
        return User::query();
    }

    public function columns(): array
    {
        return [
            Column::make('Name', 'name')->searchable()->sortable(),
            Column::make('Email', 'email')->searchable(),
            Column::make('Joined', 'created_at')->sortable()
                ->format(fn ($value) => $value->format('d/m/Y')),
        ];
    }

    public function filters(): array
    {
        return [
            SelectFilter::make('Role', 'role')->options(['admin' => 'Admin', 'member' => 'Member']),
        ];
    }
}

use Illuminate\Database\Eloquent\Builder;
use Salioudiabate\LivewireDatatable\Column;
use Salioudiabate\LivewireDatatable\DataTableComponent;

class UsersTable extends DataTableComponent
{
    public function builder(): Builder
    {
        return User::query();
    }

    public function columns(): array
    {
        return [
            Column::make('Name', 'name')->searchable()->sortable(),
            Column::make('Email', 'email')->searchable(),
        ];
    }
}

public function builder(): Builder
{
    return User::query()->where('active', true);
}

use Illuminate\Support\Facades\DB;

public function builder(): \Illuminate\Database\Query\Builder
{
    return DB::table('users')->where('active', true);
}

public function builder(): array
{
    return [
        ['id' => 1, 'name' => 'Ada Lovelace'],
        ['id' => 2, 'name' => 'Grace Hopper'],
    ];
}

use Salioudiabate\LivewireDatatable\DataSources\RawSql;

public function builder(): RawSql
{
    return RawSql::query(
        'select u.*, count(o.id) as orders_count from users u left join orders o on o.user_id = u.id group by u.id',
    );
}

Column::make('Status', 'status')
    ->format(fn ($value, $row) => ucfirst($value))   // custom display
    ->view('partials.status-badge')                   // or a full Blade partial instead of format()
    ->thView('partials.status-header')                 // custom header cell
    ->thClass('text-right')                             // extra <th> classes
    ->tdClass('text-right tabular-nums')                 // extra <td> classes, for this column only
    ->searchable()                                       //      // user can hide/show this column
    ->toggleable(visibleByDefault: false);                // ...hidden by default

use Salioudiabate\LivewireDatatable\Filters\{
    TextFilter, DateFilter, DateRangeFilter, SelectFilter,
    MultiSelectFilter, NumberFilter, NumberRangeFilter, BooleanFilter,
};

public function filters(): array
{
    return [
        TextFilter::make('Search tag', 'tag'),
        SelectFilter::make('Status', 'status')->options(['draft' => 'Draft', 'published' => 'Published']),
        MultiSelectFilter::make('Category', 'category')->options($categories),
        BooleanFilter::make('Active', 'active'),           // tri-state: Any / Yes / No
        DateFilter::make('Created on', 'created_at'),
        DateRangeFilter::make('Created between', 'created_at'),
        NumberFilter::make('Exact price', 'price'),
        NumberRangeFilter::make('Price range', 'price'),
    ];
}

SelectFilter::make('Status', 'status')->using(
    fn ($query, $value) => $query->where('status', $value)->orWhere('legacy_status', $value)
);

use Salioudiabate\LivewireDatatable\Filters\AsyncSelectFilter;

AsyncSelectFilter::make('Client', 'customer_id')
    ->optionsUsing(fn (string $term) => Customer::query()
        ->when($term !== '', fn ($query) => $query->where('name', 'like', "%{$term}%"))
        ->limit(20)
        ->pluck('name', 'id')
        ->all())
    ->labelUsing(fn (mixed $value) => Customer::find($value)?->name),

public function filters(): array
{
    $country = $this->filterValues['country'] ?? null;

    return [
        SelectFilter::make('Country', 'country')->options(Country::pluck('name', 'code')->all()),
        SelectFilter::make('Town', 'town')->options(
            $country ? Town::where('country_code', $country)->pluck('name', 'id')->all() : []
        ),
    ];
}

public function updatedFilterValuesCountry(): void
{
    unset($this->filterValues['town']);
}

SelectFilter::make('Statut', 'status')
    ->options(['draft' => 'Brouillon', 'published' => 'Publié'])
    ->cssClass('rounded-lg border border-amber-300 bg-amber-50 py-2 pl-3 pr-8 text-sm text-amber-900'),

Column::make('Name', 'name')->sortable();

public function showSearch(): bool   // default true
{
    return false;
}

public function showPerPage(): bool  // default true
{
    return false;
}

public function perPageOptions(): array
{
    return [15, 30, 60];
}

public function pollInterval(): ?int
{
    return 5000; // milliseconds
}

public function showOfflineIndicator(): bool
{
    return false; // opt out per-table
}

class UsersTableForTeamA extends UsersTable
{
    protected function urlKey(): string
    {
        return 'team-a-users';
    }
}

protected function withoutUrlBinding(): bool
{
    return true;
}

use Salioudiabate\LivewireDatatable\BulkAction;

public function bulkActions(): array
{
    return [
        BulkAction::make('exportSelected', 'Export selected')
            ->icon('<svg class="h-3.5 w-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1M7 10l5 5 5-5M12 15V3" /></svg>'),
        BulkAction::make('archiveSelected', 'Archive')
            ->confirm('Archive the selected rows?')
            ->cssClass('text-amber-600')
            ->permission('archive-users'),
    ];
}

public function archiveSelected(): void
{
    User::query()->whereIn('id', $this->getSelected())->update(['archived' => true]);
    $this->clearSelection();
}

public function recordKey(): string
{
    return 'uuid';
}

public function bulkActions(): array
{
    return [
        BulkAction::make('emailAllFiltered', 'Email everyone matching this search'),
    ];
}

public function emailAllFiltered(): void
{
    foreach ($this->allFilteredRows() as $user) {
        Mail::to($user)->queue(new WeeklyDigest);
    }
}

public function bulkActions(): array
{
    return [
        BulkAction::make('destroySelected', 'Delete')->permission('delete-users'),
    ];
}

protected function deletePermission(): ?string
{
    return 'delete-users';
}

protected function beforeDelete(mixed $row): bool
{
    return $row->id !== auth()->id(); // veto: never let a user delete themself
}

protected function afterDelete(mixed $row): void
{
    Log::info("Deleted user {$row->id}");
}

Column::make('Internal notes', 'notes')->toggleable(visibleByDefault: false);

protected function persistColumnVisibility(): ?string
{
    return 'users-table';
}

protected function defaultDensity(): string // or config('livewire-datatable.density.default')
{
    return 'compact';
}

protected function persistDensity(): ?string
{
    return 'users-table';
}

public function columns(): array
{
    return [
        Column::make('Name', 'name')->frozen(200),
        Column::make('Email', 'email'),
        // ...many more columns that scroll under "Name"
    ];
}

public function stickyHeader(): bool
{
    return true;
}

protected function stickyHeaderMaxHeight(): string
{
    return '600px'; // any valid CSS length — default '70vh'
}

public function footer(): array
{
    $count = $this->filteredDataSource()->count();

    if ($count === 0) {
        return [];
    }

    return [
        ['label' => 'Products', 'value' => (string) $count, 'align' => 'left'],
        ['label' => 'Total stock value', 'value' => number_format(
            (float) $this->filteredDataSource()->aggregate('sum', 'price'), 2
        ).' €'],
    ];
}

protected function exportFilename(): string
{
    return 'users-'.now()->format('Y-m-d').'.csv';
}

protected function exportColumns(): array
{
    return $this->columns(); // ignore visibility toggles, always export everything
}

use Salioudiabate\LivewireDatatable\Export\ExcelExporter;
use Salioudiabate\LivewireDatatable\Export\Exporter;

protected function exporter(): Exporter
{
    return new ExcelExporter();
}

protected function exportFilename(): string
{
    return 'users-'.now()->format('Y-m-d').'.xlsx';
}

use Salioudiabate\LivewireDatatable\Export\PdfExporter;

protected function exporter(): Exporter
{
    return new PdfExporter();
}

protected function exportFilename(): string
{
    return 'users-'.now()->format('Y-m-d').'.pdf';
}

use Salioudiabate\LivewireDatatable\RowAction;

public function rowActions(): array
{
    return [
        RowAction::make('Edit')->url(fn ($user) => route('users.edit', $user)),
        RowAction::make('Delete')
            ->action('deleteUser')
            ->confirm('Delete this user?')
            ->visible(fn ($user) => $user->id !== auth()->id()),
    ];
}

public function deleteUser(string $id): void
{
    User::query()->whereKey($id)->delete();
}

public function rowUrl(mixed $row): ?string
{
    return route('users.edit', $row);
}

use Salioudiabate\LivewireDatatable\ToolbarAction;
use Salioudiabate\LivewireDatatable\ToolbarActionGroup;

public function toolbarActions(): array
{
    return [
        ToolbarAction::make('New product')
            ->dispatch('openModal', ['component' => 'product.create-modal'])  // fires Livewire's $dispatch()
            ->cssClass('bg-[var(--dt-primary,#4f46e5)] text-white hover:opacity-90')
            ->permission('products.create'),

        ToolbarAction::make('Docs')->url('https://example.com/docs', target: '_blank')->align('left'),

        ToolbarActionGroup::make([
            ToolbarAction::make('Sort by price')->action('sortByPrice'),
            ToolbarAction::make('Sort by stock')->action('sortByStock'),
        ]),
    ];
}

public function sortByPrice(): void
{
    $this->sortBy('price');
}

    ToolbarAction::make('Export as PDF')
        ->submit(
            action: route('products.export-pdf'),
            data: fn () => ['status' => $this->filterValues['status'] ?? null, 'search' => $this->search],
            target: '_blank',
        )
        ->confirm('Generate a PDF of the current results?'),
    

ToolbarActionGroup::make([
    ToolbarAction::make('Sort by price')->action('sortByPrice'),
    ToolbarAction::make('Sort by stock')->action('sortByStock'),
    ToolbarAction::make('Sort by name')->action('sortByName'),
])->dropdown('Sort by...'),

'theme' => [
    'primary' => '#4f46e5',
    'primary_hover' => '#4338ca',
    'primary_dark' => '#3730a3',
    'primary_light' => '#eef2ff',
    'primary_text' => '#ffffff',
],

// Config-level — the value is emitted verbatim, so it can itself be a var() reference
'theme' => [
    'primary' => 'var(--brand-primary)',
],

protected function tableWrapperClasses(): string
{
    return 'overflow-x-auto rounded-2xl border border-slate-300';
}

protected function toolbarClasses(): string
{
    return 'mb-6 flex flex-wrap items-center justify-between gap-4';
}

public function emptyStateView(): ?string
{
    return 'partials.no-products-yet';
}

use Salioudiabate\LivewireDatatable\DataSources\DataSourceFactory;

DataSourceFactory::extend(YourQueryType::class, fn ($query) => new YourDataSource($query));
bash
php artisan vendor:publish --tag=livewire-datatable-config
bash
php artisan vendor:publish --tag=livewire-datatable-views
js
// tailwind.config.js
export default {
  content: [
    // ...your own paths
    './vendor/salioudiabate/livewire-datatable/resources/views/**/*.blade.php',
  ],
};
css
/* Tailwind v4, in your main CSS file */
@source '../../vendor/salioudiabate/livewire-datatable/resources/views/**/*.blade.php';
bash
php artisan make:datatable UsersTable --model=User
bash
php artisan vendor:publish --tag=livewire-datatable-translations