PHPackages                             team-nifty-gmbh/tall-datatables - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. team-nifty-gmbh/tall-datatables

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

team-nifty-gmbh/tall-datatables
===============================

A package to create datatables using alpinejs, tailwind, livewire and laravel

v1.8.0(1mo ago)1217.2k—4.8%[6 PRs](https://github.com/Team-Nifty-GmbH/tall-datatables/pulls)1MITPHPPHP ^8.1CI passing

Since Jan 31Pushed 2mo ago1 watchersCompare

[ Source](https://github.com/Team-Nifty-GmbH/tall-datatables)[ Packagist](https://packagist.org/packages/team-nifty-gmbh/tall-datatables)[ Docs](https://github.com/team-nifty-gmbh/tall-datatables)[ RSS](/packages/team-nifty-gmbh-tall-datatables/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (26)Versions (180)Used By (1)

A package to create datatables using alpinejs, tailwind, livewire and laravel
=============================================================================

[](#a-package-to-create-datatables-using-alpinejs-tailwind-livewire-and-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/9abac1f32ff1aa87b3dbdcc8920bcf6c38af38dc87285c3017af6ee4990f98a9/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f7465616d2d6e696674792d676d62682f74616c6c2d646174617461626c65732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/team-nifty-gmbh/tall-datatables)[![GitHub Tests Action Status](https://camo.githubusercontent.com/5d2a72775ebc946640a325178a8a3d30f0b23c8c6fde76ace41c87d01870d023/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f5465616d2d4e696674792d476d62482f74616c6c2d646174617461626c65732f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/Team-Nifty-GmbH/tall-datatables/actions?query=workflow%3ATests+branch%3Amain)[![GitHub Code Style Action Status](https://camo.githubusercontent.com/b69da1cb1670c3d0e79bf55a2d57b4d14dea0c433beff87ab7fde709cc67ab5f/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7465616d2d6e696674792d676d62682f74616c6c2d646174617461626c65732f6669782d7068702d636f64652d7374796c652d6973737565732e796d6c3f6272616e63683d6d61696e266c6162656c3d636f64652532307374796c65267374796c653d666c61742d737175617265)](https://github.com/team-nifty-gmbh/tall-datatables/actions?query=workflow%3A%22Fix+PHP+code+style+issues%22+branch%3Amain)[![Total Downloads](https://camo.githubusercontent.com/27b7600b09dd053e21c00e5a9dbecbc27c1e546b9d14a6576acdc9c8e4985d57/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f7465616d2d6e696674792d676d62682f74616c6c2d646174617461626c65732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/team-nifty-gmbh/tall-datatables)

This package aims to provide a simple way to create datatables using alpinejs, tailwind, livewire and laravel.

It relies mainly on alpinejs to avoid re-rendering the whole table when something changed.

[![img_1.png](resources%2Fimages%2Fimg_1.png)](resources%2Fimages%2Fimg_1.png)

Requirements
------------

[](#requirements)

- PHP &gt;= 8.1
- Laravel &gt;= 9.46
- AlpineJS &gt;= 3.0
- TailwindCSS &gt;= 3.0
- Livewire &gt;= 2.11
- Vite &gt;= 4.0
- MeiliSearch &gt;= 1.0

Installation
------------

[](#installation)

1. You can install the package via composer:

```
composer require team-nifty-gmbh/tall-datatables
```

2. Add the scripts tag to your layout BEFORE alpinejs

```
...

@dataTablesScripts @vite(['resources/js/alpine.js']) ...
```

3. Add the following to your tailwind.config.mjs

```
module.exports = {
    presets: [
        ...
        require('./vendor/team-nifty-gmbh/tall-datatables/tailwind.config.mjs')
    ],
    content: [
        ...
        './vendor/team-nifty-gmbh/tall-datatables/resources/views/**/*.blade.php',
        './vendor/team-nifty-gmbh/tall-datatables/resources/js/**/*.js',
    ],
    ...
}
```

4. Run vite build to compile the javascript and css files

```
vite build
```

5. Publishing the views is optional. If you want to use the default views you can skip this step.

Optionally, you can publish and run the migrations with:

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

Optionally, you can publish the config file with:

```
php artisan vendor:publish --tag="tall-datatables-config"
```

Optionally, you can publish the views using

```
php artisan vendor:publish --tag="tall-datatables-views"
```

Configuration
-------------

[](#configuration)

By default the package caches the state of the table in the session. If you want to disable this feature, you can set the `cache` option to false in the .env file.

```
TALL_DATATABLES_CACHE=false
```

The caching is done per datatable. If you want to use your datatable in a different context you should set a different cache key. In your blade file pass the cache key to the component.

```

```

You have to ensure that all cache-keys you set across your application are unique.

Usage
=====

[](#usage)

This command creates a new DataTable class.

```
php artisan make:data-table UserDataTable "App\Models\User"
```

Inside this class you should define at least the columns you want to display

```
public array $enabledCols = [
    'id',
    'name',
    'email',
    'email_verified_at',
    'created_at',
    'updated_at',
];
```

### Choosing a layout

[](#choosing-a-layout)

By default, the table is rendered as a table. You can change the layout by overriding the `getLayout` method.

```
public function getLayout(): string
{
    return 'tall-datatables::layouts.grid';
}
```

This package delivers 2 layouts: 'tall-datatables::layouts.grid' and 'tall-datatables::layouts.table'

You can also create your own layout by creating a blade file inside the `resources/views/components` folder.

[![grid_layout.png](resources%2Fimages%2Fgrid_layout.png)](resources%2Fimages%2Fgrid_layout.png)

### Using your own view

[](#using-your-own-view)

If you want to use your own view as a wrapper around the layout you can override the `$view` property.

```
protected string $view = 'data-tables.my-custom-view';
```

Your view should include the default data-table wrapper:

```

    hey i'm rendered above the table
    @include('tall-datatables::livewire.data-table')

```

### Adding Buttons to the table

[](#adding-buttons-to-the-table)

You can add buttons to the table by overriding the getTableActions method.

These buttons will be rendered above the table on the right side. If your table has search enabled, the buttons will be rendered on the right side of the search input.

> ***NOTE:*** My advice is to embed the datatable inside another component and use the `wire:ignore` directive to avoid re-rendering the whole page. The "Create" button could dispatch an alpinejs event to the parent component. The listener could trigger a livewire function to render the create form.

```
use TeamNiftyGmbH\DataTable\Htmlables\DataTableButton;

...

public function getTableActions(): array
{
    return [
        DataTableButton::make()
            ->text('Create')
            ->icon('plus')
            ->color('indigo')
            ->attributes([
                'x-on:click' => '$dispatch(\'create-user\')',
            ]),
    ];
}
```

### Adding Buttons to a row

[](#adding-buttons-to-a-row)

> ***NOTE:*** Keep in mind that tall-datatables relies on alpinejs to render the data.
>
> Each row is rendered using the `x-for` directive. This means that every record is available as a variable called `record`.
>
> Remember that the record variable contains only the columns that are returned by the `getReturnKeys` php method. The Model key is always available.

You can add buttons to a row by overriding the getRowActions method.

```
use TeamNiftyGmbH\DataTable\Htmlables\DataTableButton;

...

public function getRowActions(): array
{
    return [
        \TeamNiftyGmbH\DataTable\Htmlables\DataTableButton::make()
            ->text('Edit')
            ->icon('eye')
            ->color('indigo')
            ->attributes([
                'x-on:click' => '$wire.edit(record.id)',
                'x-bind:class' => 'record.is_locked ? \'hidden\' : \'\''
            ]),
        \TeamNiftyGmbH\DataTable\Htmlables\DataTableButton::make()
            ->text('Delete')
            ->icon('trash')
            ->color('red'),
    ];
}
```

> ***TIP:*** If you want to prevent the row-clicked event to be dispatched on a button click add the $event.stopPropagation() method to the button attributes.
>
> ```
> DataTableButton::make()
>    ->text('Edit')
>    ->icon('pencil')
>    ->color('indigo')
>    ->attributes([
>        'x-on:click' => '$wire.edit(record.id); $event.stopPropagation()', //       ]),
> ```

Combining Columns
-----------------

[](#combining-columns)

You can combine multiple columns into one by overwrite the get{Position}Appends. As the name states the defined columns will be appended to the position.

```
public function getBottomAppends(): array
{
    return [
        'name' => 'email',
    ];
}

public function getLeftAppends(): array
{
    return [
        'name' => 'avatar',
    ];
}
```

This function would append the email below the name in the name column. This is just for view purposes. The data is still available in the record variable. Also, all formatters are applied before the column is appended.

> ***NOTE:*** Keep in mind to add the appended Columns to the `getReturnKeys` method.

### Eager Loading

[](#eager-loading)

If you need to eager load additional data you can override the getBuilder method

```
protected function getBuilder(Builder $builder): Builder
{
    return $builder->with('roles');
}
```

### Minimized Network traffic

[](#minimized-network-traffic)

The datatable component will only return the columns you defined in the enabledCols property. In case you need a specific column to be always returned you can override the getReturnKeys method.

This is especially needed when you want to format money values in the frontend.

```
protected function getReturnKeys(): array
{
    return array_merge(parent::getReturnKeys(), ['currency.iso']);
}
```

### Using your DataTable inside another component

[](#using-your-datatable-inside-another-component)

To use this new Data table you can add a livewire tag in your blade file:

```

```

You can pass contextual attributes when you call the component like this:

```

```

This keeps your component reusable, and you can use it in different contexts.

### Using your DataTable as a full page component

[](#using-your-datatable-as-a-full-page-component)

To use this new Data table as a full page component you can just point a route to the component. See the [Livewire documentation](https://laravel-livewire.com/docs/2.x/rendering-components#page-components) for more information.

```
Route::get('/users', \App\Http\Livewire\DataTables\UserDataTable::class);
```

### Row clicked

[](#row-clicked)

> ***NOTE:*** The data-table-row-clicked event is always dispatched, however if your record has the InteractsWithDataTables interface implemented the getUrl() method will be called to get the url to redirect to.
>
> If you just need the click event without a redirect you can set the `$hasNoRedirect` property to true.

```
public function getUrl(): string
{
    return route('users.show', $this->id);
}
```

Every row click dispatches a `data-table-row-clicked` event with the model as payload. You can listen to this event in your AlpineJS.

```

```

If you want to use your clicked row with livewire my recommendation is to use the `$wire` property from alpinejs.

```

```

Echo and Eloquent Events
------------------------

[](#echo-and-eloquent-events)

If you want to listen to eloquent events that occur on the model you can use the `HasEloquentListeners` trait in your Datatable. This trait will automatically register the Echo event listeners for `created`, `updated` and `deleted` events.

Your models should use the BroadcastsEvents trait from this package.

```
use TeamNiftyGmbH\DataTable\Traits\BroadcastsEvents;

class User extends Authenticatable
{
    use BroadcastsEvents;
}
```

You have to define your Authentication callbacks like this:

```
Broadcast::channel(App\Models\User::class, function ($user, $id) {
    return $user->id === (int) $id;
});
```

To have `created` events working you have to add an aditional route:

```
Broadcast::channel(\App\Models\User::getBroadcastChannel(), function ($user) {
    return true;
});
```

Prepare your model
==================

[](#prepare-your-model)

HasFrontendFormatter trait
--------------------------

[](#hasfrontendformatter-trait)

If you want to format the data for the frontend you should use the HasFrontendAttributes trait in your model. This trait will add a method to your model called `getFrontendAttributes()`

Also, you should define a detailRouteName property in your model which points to a view showing the details of the model.

```
use TeamNifty\TallDatatables\Traits\HasFrontendAttributes;

class User extends Authenticatable
{
    use HasFrontendAttributes;

    protected string $detailRouteName = 'users.id';
    ...
}
```

If your detail route needs additional parameters you can override the `getDetailRouteParameters()` method in your model class.

```
public function getDetailRouteParameters(): array
{
    return [
        'id' => $this->id,
        'foo' => 'bar',
    ];
}
```

The trait adds an attribute accessor to your model which contains the detail route for a single model instance.

```
$user = User::first();
$user->href; // returns the detail route for the user
```

Styling the table
-----------------

[](#styling-the-table)

### Adding Attributes to a row

[](#adding-attributes-to-a-row)

You can add attributes to a row by overriding the getRowAttributes method.

```
use TeamNiftyGmbH\DataTable\Htmlables\DataTableRowAttributes;

...

public function getRowAttributes(): array
{
    return DataTableRowAttributes::make()
        ->bind('class', 'record.is_active ? \'bg-green-100\' : \'bg-red-100\'')
        ->on('click', 'alert($event.detail.record.id)')
        ->class('cursor-pointer')
}
```

### Infinite Scrolling

[](#infinite-scrolling)

By default, the table shows pagination. If you want to use infinite scrolling you can set the `hasInfiniteScroll` property to true.

```
public bool $hasInfiniteScroll = true;
```

When the end of the table comes into viewport the table adds the amount of records you defined in the `perPage` property. Please keep in mind that the network traffic grows each time as livewire has to hydrate the whole data not just add the new records.

> ***NOTE:*** If you use infinite scrolling you need to import the alpinejs intersect plugin in your main projects js file.

```
import Alpine from 'alpinejs';
import intersect from '@alpinejs/intersect';

Alpine.plugin(intersect);

window.Alpine = Alpine;

Alpine.start();
```

### Show filter inputs below column names

[](#show-filter-inputs-below-column-names)

If you want to show the filter inputs below the column names you can set the `showFilterInputs` property to true.

```
public bool $showFilterInputs = true;
```

### Hiding the header

[](#hiding-the-header)

If you want to hide the header you can set the `hasHeader` property to false.

```
public bool $hasHeader = false;
```

The sidebar with the filters are still available, but you have to add your own button to show it.

### Icons

[](#icons)

You can set an iconName property in your model which will be used to display an icon in the table. You can set any icon from the [heroicons](https://heroicons.com/) library.

```
protected string $iconName = 'user';
```

InteractsWithDataTables interface
---------------------------------

[](#interactswithdatatables-interface)

If a model is used in a relation of a model that has a datatable you should implement the `TeamNifty\TallDatatables\Contracts\InteractsWithDataTables` interface. This interface will add two methods to your model.

```
use TeamNifty\TallDatatables\Contracts\InteractsWithDataTables;

class User extends Authenticatable implements InteractsWithDataTables
{
    ...

    public function getLabel(): string
    {
        return $this->name;
    }

    public function getDescription(): string
    {
        return $this->email;
    }
}
```

Casts
-----

[](#casts)

The Package uses casts to format the data for the frontend. You can define your own casts in the `casts` property of your model. Aside from the primitive cast you can add your own casts. These cast classes should implement the `TeamNifty\TallDatatables\Contracts\HasFrontendFormatter` interface which brings the `getFrontendFormatter()` method.

```
use TeamNifty\TallDatatables\Casts\Date;
```

Searchable
----------

[](#searchable)

If you want to search in your datatable you should use the Searchable trait from laravel scout. The package will automatically detect if your model is searchable and will add a search input to the datatable.

If you don't want to use the search input you can set the isSearchable property to false in your DataTable.

```
public bool $isSearchable = false;
```

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information on what has changed recently.

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Security Vulnerabilities
------------------------

[](#security-vulnerabilities)

Please review [our security policy](../../security/policy) on how to report security vulnerabilities.

Credits
-------

[](#credits)

- [Patrick Weh](https://github.com/patrickweh)
- [All Contributors](../../contributors)

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

56

—

FairBetter than 98% of packages

Maintenance86

Actively maintained with recent releases

Popularity34

Limited adoption so far

Community16

Small or concentrated contributor base

Maturity73

Established project with proven stability

 Bus Factor1

Top contributor holds 89.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~7 days

Total

154

Last Release

51d ago

Major Versions

v0.9.21 → v1.0.0-beta.12024-12-08

v0.9.37 → v1.0.0-beta.22025-02-26

v0.9.38 → v1.0.0-beta.52025-03-14

0.x-dev → v1.0.0-beta.82025-04-10

1.x-dev → 2.x-dev2026-03-28

PHP version history (2 changes)v0.1.0PHP ^8.1

2.x-devPHP ^8.4

### Community

Maintainers

![](https://www.gravatar.com/avatar/315f809551baee16f7c5531f89a864b4d5b59bde8882779c30d4a01ae36e718e?d=identicon)[team-nifty](/maintainers/team-nifty)

---

Top Contributors

[![patrickweh](https://avatars.githubusercontent.com/u/40495041?v=4)](https://github.com/patrickweh "patrickweh (604 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (27 commits)")[![SirSplasch](https://avatars.githubusercontent.com/u/27318897?v=4)](https://github.com/SirSplasch "SirSplasch (27 commits)")[![nehegeb](https://avatars.githubusercontent.com/u/35218212?v=4)](https://github.com/nehegeb "nehegeb (10 commits)")[![github-actions[bot]](https://avatars.githubusercontent.com/in/15368?v=4)](https://github.com/github-actions[bot] "github-actions[bot] (4 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (2 commits)")[![Slupi](https://avatars.githubusercontent.com/u/866949?v=4)](https://github.com/Slupi "Slupi (1 commits)")

---

Tags

laravelteam-nifty-gmbhtall-datatables

###  Code Quality

TestsPest

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/team-nifty-gmbh-tall-datatables/health.svg)

```
[![Health](https://phpackages.com/badges/team-nifty-gmbh-tall-datatables/health.svg)](https://phpackages.com/packages/team-nifty-gmbh-tall-datatables)
```

###  Alternatives

[livewire/volt

An elegantly crafted functional API for Laravel Livewire.

4205.3M84](/packages/livewire-volt)[mediconesystems/livewire-datatables

Advanced datatables using Laravel, Livewire, Tailwind CSS and Alpine JS

1.2k711.3k8](/packages/mediconesystems-livewire-datatables)[ramonrietdijk/livewire-tables

Dynamic tables for models with Laravel Livewire

21147.4k](/packages/ramonrietdijk-livewire-tables)[tomshaw/electricgrid

A feature-rich Livewire package designed for projects that require dynamic, interactive data tables.

116.6k](/packages/tomshaw-electricgrid)[marcorieser/statamic-livewire

A Laravel Livewire integration for Statamic.

2381.5k10](/packages/marcorieser-statamic-livewire)[ralphjsmit/livewire-urls

Get the previous and current url in Livewire.

82270.3k4](/packages/ralphjsmit-livewire-urls)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
