Laravel 12 – 13
PHP 8.4+
The project is in a healthy, maintained state
Server-side rendered datatables for Laravel and Livewire
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Development

pestphp/pest-plugin-browser
^4.0
pestphp/pest-plugin-faker
^4.0
pestphp/pest-plugin-livewire
^4.0

Runtime

 Project Readme

Tall DataTables

Latest Version on Packagist GitHub Tests Action Status Total Downloads

Performant, feature-rich datatables for the TALL stack. Built on Livewire 4 Islands architecture with Alpine.js driven rendering for minimal payloads.

Requirements

  • PHP 8.4+
  • Laravel 12+
  • Livewire 4+
  • TallStackUI 3+
  • Alpine.js 3+
  • Tailwind CSS 3+

Installation

composer require team-nifty-gmbh/tall-datatables:^2.0

Add the scripts and styles to your layout:

<datatable:styles />
<datatable:scripts />

Publish migrations and run them:

php artisan vendor:publish --tag="tall-datatables-migrations"
php artisan migrate

Quick Start

class UserDataTable extends DataTable
{
    protected string $model = User::class;

    public array $enabledCols = ['name', 'email', 'created_at'];
}
<livewire:data-tables.user-data-table />

Layouts

Three built-in layouts: table (default), grid, and kanban.

View-Mode Switcher

Let users switch between layouts at runtime:

protected function availableLayouts(): array
{
    return ['table', 'grid', 'kanban'];
}

When more than one layout is configured, a switcher appears in the toolbar. The active layout is persisted in saved filters.

Grid Layout

Cards in a responsive CSS grid. Image columns get hero treatment.

protected function availableLayouts(): array
{
    return ['table', 'grid'];
}

Kanban Layout

Cards grouped into lanes by a column value. Drag & drop between lanes.

protected function availableLayouts(): array
{
    return ['table', 'kanban'];
}

// Which column determines the lanes
protected function kanbanColumn(): string
{
    return 'state';
}

// Optional: explicit lane config (order, labels, colors)
protected function kanbanLanes(): ?array
{
    return [
        'open' => ['label' => 'Open', 'color' => 'emerald'],
        'in_progress' => ['label' => 'In Progress', 'color' => 'amber'],
        'done' => ['label' => 'Done', 'color' => 'indigo'],
    ];
}

// Handle drag & drop
public function kanbanMoveItem(int|string $id, string $targetLane): void
{
    MyModel::findOrFail($id)->update(['state' => $targetLane]);
}

// Optional: custom card blade view
protected function kanbanCardView(): ?string
{
    return 'components.my-kanban-card';
}

If kanbanLanes() returns null, lanes are auto-generated from the column's enum/state values.

Filtering

Sidebar Filters

Enable filtering with the sidebar:

public bool $isFilterable = true;

Available operators: =, !=, >, >=, <, <=, like, not like, starts with, ends with, contains, does not contain, in, not in, is null, is not null, between.

The in and not in operators accept comma-separated values.

Date Presets

Date columns automatically show a preset dropdown: Today, Yesterday, This Week/Month/Quarter/Year, Last 7/30 Days, Last Week/Month/Quarter/Year. A "Custom" option opens inline fields for building custom relative date calculations.

Saved Filters

Users can save their current filter/column/sort configuration and reload it later. Supports shared filters across team members:

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

Sorting

Click a column header to sort. Shift+Click for multi-sort on additional columns.

// Restrict sortable columns (default: all)
public array $sortable = ['name', 'created_at'];

Selection

public bool $isSelectable = true;

Select individual rows or use "select all" (wildcard). The wildcard stays compact (['*']) regardless of record count. Use getSelectedValues() or getSelectedModels() in your actions to resolve the actual records.

Relation Columns

Display columns from related models using dot notation:

public array $enabledCols = [
    'name',
    'email',
    'department.name',
    'department.manager.email',
];

Relation Count Columns

Show relation counts by adding _count suffix in the column configuration. Counts are filterable and sortable:

public array $enabledCols = ['name', 'orders_count', 'comments_count'];

Export

Export data in three formats: Excel (.xlsx), CSV, and JSON. Users select the format from a dropdown in the export tab.

// Disable export (enabled by default)
public bool $isExportable = false;

CSV uses semicolon delimiter with UTF-8 BOM for Excel compatibility. JSON exports relations as nested objects.

Row Actions

Define actions using DataTableButton:

protected function getRowActions(): array
{
    return [
        DataTableButton::make('edit')
            ->label(__('Edit'))
            ->icon('pencil')
            ->wireClick('edit(record.id)'),
    ];
}

Row Drag & Drop

Enable manual row reordering:

protected function getRowDragDropConfig(): ?array
{
    return [
        'column' => 'sort_order',
    ];
}

Custom Formatters

Register formatters for custom display logic:

use TeamNiftyGmbH\DataTable\Formatters\FormatterRegistry;

app(FormatterRegistry::class)->register(MyCast::class, new MyFormatter());

Built-in formatters: boolean, date, datetime, money, percentage, image, link, badge, float, string, array.

Custom Column Transformation

Use augmentItemArray() to add computed columns before formatters are applied:

protected function augmentItemArray(array &$itemArray, Model $item): void
{
    $itemArray['full_name'] = $item->first_name . ' ' . $item->last_name;
}

Sidebar Tabs

Extend the sidebar with custom tabs:

public function getSidebarTabs(): array
{
    $tabs = parent::getSidebarTabs();

    $tabs[] = [
        'id' => 'my-tab',
        'label' => __('My Tab'),
        'view' => 'components.my-custom-tab',
    ];

    return $tabs;
}

Positive Empty State

Show a friendly message when a table is expected to be empty:

public bool $positiveEmptyState = true;

Default Columns

Allow users to save their column layout as the default:

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

Testing

vendor/bin/pest

Credits

License

MIT. See LICENSE.