PHPackages                             tomshaw/electricgrid - 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. tomshaw/electricgrid

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

tomshaw/electricgrid
====================

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

v2.3.1(1mo ago)116.6k—6.7%3MITPHPPHP ^8.2|^8.3|^8.4|^8.5CI passing

Since Feb 11Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/tomshaw/electricgrid)[ Packagist](https://packagist.org/packages/tomshaw/electricgrid)[ Docs](https://github.com/tomshaw/electricgrid)[ RSS](/packages/tomshaw-electricgrid/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (24)Versions (72)Used By (0)

Electric Grid 🔌
===============

[](#electric-grid-)

A powerful Livewire data table package. A great choice for projects that require a data table solution.

[![GitHub Workflow Status](https://camo.githubusercontent.com/68f2dedd6072ea9e11f85b7129d6d35d3da669581be825e61cee18aa83afc9f5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f746f6d736861772f656c656374726963677269642f72756e2d74657374732e796d6c3f6272616e63683d6d6173746572267374796c653d666c6174266c6162656c3d7465737473)](https://camo.githubusercontent.com/68f2dedd6072ea9e11f85b7129d6d35d3da669581be825e61cee18aa83afc9f5/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f746f6d736861772f656c656374726963677269642f72756e2d74657374732e796d6c3f6272616e63683d6d6173746572267374796c653d666c6174266c6162656c3d7465737473)[![issues](https://camo.githubusercontent.com/6f2b355c5f434c77e86ccebc93e5f091df2b0d484abd1212f1a808ff7993f424/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f746f6d736861772f656c656374726963677269643f7374796c653d666c6174266c6f676f3d676974687562)](https://camo.githubusercontent.com/6f2b355c5f434c77e86ccebc93e5f091df2b0d484abd1212f1a808ff7993f424/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6973737565732f746f6d736861772f656c656374726963677269643f7374796c653d666c6174266c6f676f3d676974687562)[![forks](https://camo.githubusercontent.com/3abd16bf8e2d3c0ea50ab6d627a45109ac1b63ce2527eef7f3990de6c6c5d488/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f746f6d736861772f656c656374726963677269643f7374796c653d666c6174266c6f676f3d676974687562)](https://camo.githubusercontent.com/3abd16bf8e2d3c0ea50ab6d627a45109ac1b63ce2527eef7f3990de6c6c5d488/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f666f726b732f746f6d736861772f656c656374726963677269643f7374796c653d666c6174266c6f676f3d676974687562)[![stars](https://camo.githubusercontent.com/78008667e85be1074c81b830cd3e4a936dfdc76a5c8e8a0202395a63c9bad884/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f746f6d736861772f656c656374726963677269643f7374796c653d666c6174266c6f676f3d676974687562)](https://camo.githubusercontent.com/78008667e85be1074c81b830cd3e4a936dfdc76a5c8e8a0202395a63c9bad884/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f73746172732f746f6d736861772f656c656374726963677269643f7374796c653d666c6174266c6f676f3d676974687562)[![GitHub license](https://camo.githubusercontent.com/c1d49cc7d201b83f8ec2556ab6028213cb3be840e2a4661324db21388408d19b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f6c6963656e73652f746f6d736861772f656c656374726963677269643f7374796c653d666c6174)](https://github.com/tomshaw/electricgrid/blob/master/LICENSE)

Features
--------

[](#features)

1. **Easy Installation**: Use a simple command for installation and package updates.
2. **Columns**: Add columns to your grid with various options including sortable, styleable, exportable and visible.
3. **Filters**: Supports text, number, select, multiselect, boolean, timepicker, datepicker, and datetimepicker.
4. **Mass Actions**: Provides the capability to execute operations on multiple rows of data simultaneously.
5. **Table Exports**: Tables can be exported in various formats including xlsx, csv, pdf, and html out of the box.
6. **Search Input**: You can enable search functionality by specifying the columns you wish to search.
7. **Letter Search**: This feature allows you to search data based on specific letters in the specified columns.
8. **Toggleable Columns**: Hide or show columns useful for focusing on the most relevant data.
9. **Smart Pagination**: Intelligent per-page controls that automatically hide when unnecessary and filter options based on dataset size.
10. **Themes**: Uses a single blade template under 230 lines of html making it super easy to theme.
11. **Testing**: Provides a command for running tests to ensure everything works as expected.

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

[](#installation)

You can install the package via composer:

```
composer require tomshaw/electricgrid
```

Run the installation command.

```
php artisan electricgrid:install

```

Run the update command for package updates:

```
php artisan electricgrid:update

```

Make sure to add the styles and scripts directives to your layout.

```
@vite(['resources/css/app.css', 'resources/js/app.js'])

@electricgridStyles
@electricgridScripts
```

Add the component to your blade template where you plan to use it.

> Here the namespace is `App\Livewire\Tables` and the component name is `OrdersTable`.

```

```

Usage
-----

[](#usage)

### The Builder Method.

[](#the-builder-method)

Populating your table is done by using the `builder` method. It supports both database queries and in-memory data sources.

> The builder method can return an Eloquent `Builder` for database queries, or a `DatabaseCollection`, `Collection`, or `array` for in-memory data.

#### Eloquent Builder

[](#eloquent-builder)

Return an Eloquent `Builder` for standard database-backed tables with full query support:

```
use Illuminate\Database\Eloquent\Builder;
use TomShaw\ElectricGrid\Component;
use App\Models\User;

class UsersTable extends Component
{
    public array $computedColumns = ['posts_count'];

    public function builder(): Builder
    {
        return User::with(['roles', 'profile'])->withCount('posts');
    }
}
```

#### Collection &amp; Array Data Sources

[](#collection--array-data-sources)

Return a `DatabaseCollection`, `Collection`, or plain `array` to power tables with in-memory data. This is useful for displaying data from APIs, config files, or any non-database source. All standard features including sorting, filtering, pagination, and exports work with collection data sources.

```
use Illuminate\Support\Collection;
use TomShaw\ElectricGrid\Component;

class ProductsTable extends Component
{
    public function builder(): Collection
    {
        return collect([
            ['id' => 1, 'name' => 'Widget', 'price' => 9.99],
            ['id' => 2, 'name' => 'Gadget', 'price' => 24.99],
            ['id' => 3, 'name' => 'Gizmo', 'price' => 14.99],
        ]);
    }
}
```

You can also return a plain array:

```
public function builder(): array
{
    return [
        ['id' => 1, 'name' => 'Widget', 'price' => 9.99],
        ['id' => 2, 'name' => 'Gadget', 'price' => 24.99],
    ];
}
```

### Adding Columns.

[](#adding-columns)

Use Columns to present data in your grid.

```
use TomShaw\ElectricGrid\{Component, Column};
use NumberFormatter;

class OrdersTable extends Component
{
    public function columns(): array
    {
        $numberFormat = new NumberFormatter('en_US', NumberFormatter::CURRENCY);

        return [
            Column::add('id', 'ID')
                ->sortable()
                ->stylable('text-center w-20')
                ->exportable(),

            Column::add('name', 'Customer')
                ->callback(function (Model $model) {
                    return view('livewire.tables.users-customer', ['model' => $model]);
                })
                ->exportCallback(fn (Model $model) => $model->name)
                ->searchable()
                ->sortable()
                ->exportable(),

            Column::add('status', 'Status')
                ->callback(function (Order $order) {
                    return OrderStatus::from($order->status)->name();
                })
                ->sortable()
                ->exportable(),

            Column::add('total', 'Total')
                ->callback(fn (Order $order) => $numberFormat->formatCurrency($order->total, 'USD'))
                ->searchable()
                ->sortable()
                ->exportable(),

            Column::add('invoiced', 'Invoiced')
                ->callback(fn (Order $order) => $order->invoiced ? 'Yes' : 'No')
                ->sortable()
                ->exportable(),

            Column::add('created_at', 'Created At')
                ->callback(fn (Order $order) => Carbon::parse($order->created_at)->format('F j, Y, g:i a'))
                ->sortable()
                ->exportable(),

            Column::add('updated_at', 'Updated At')
                ->callback(fn (Order $order) => Carbon::parse($order->updated_at)->format('F j, Y, g:i a'))
                ->sortable()
                ->exportable()
                ->visible(false),

        ];
    }
}
```

### Column Aggregates

[](#column-aggregates)

Columns support aggregate calculations that display in the table footer.

#### Summable Columns

[](#summable-columns)

Add `.summable()` to display column totals:

```
Column::add('total', 'Total')
    ->summable(),

Column::add('quantity', 'Quantity')
    ->summable(),
```

#### Averageable Columns

[](#averageable-columns)

Add `.averageable()` to display column averages:

```
Column::add('rating', 'Rating')
    ->averageable(),

Column::add('price', 'Price')
    ->averageable(),
```

#### Combined Aggregates

[](#combined-aggregates)

Columns can display both sum and average:

```
Column::add('amount', 'Amount')
    ->summable()
    ->averageable(),
```

When both aggregates are present, they display as:

- **Sum: 1,500.00**
- **Avg: 150.00**

### Column Filters.

[](#column-filters)

Filters allow you to filter data displayed in the grid.

> Data attributes can be added to filters using the `addDataAttribute` method.

```
use TomShaw\ElectricGrid\{Component, Column, Filter};
use App\Enums\OrderStatus;

class OrdersTable extends Component
{
    public function filters(): array
    {
        return [
            Filter::number('id')->placeholders('Min', 'Max'),
            Filter::text('name')->placeholder('Customer'),
            Filter::select('status')->options(OrderStatus::toOptions()),
            Filter::number('total')->placeholders('Min Total', 'Max Total'),
            Filter::boolean('invoiced')->labels('Yes', 'No'),
            Filter::datepicker('created_at')->addDataAttribute('format', 'H:i'),
            Filter::datetimepicker('updated_at'),
        ];
    }
}
```

#### Filter::number('id')

[](#filternumberid)

This creates a number filter for the 'id' field.

- `placeholders('Min', 'Max')`: Sets the placeholder text for the minimum and maximum input fields.

#### Filter::text('name')

[](#filtertextname)

This creates a text filter for the 'name' field.

- `placeholder('Customer')`: Sets the placeholder text for the input field.

#### Filter::select('status')

[](#filterselectstatus)

This creates a select filter for the 'status' field.

- `options(OrderStatus::toOptions())`: Sets the options for the select field using the `toOptions` method of the `OrderStatus` class.

#### Filter::number('total')

[](#filternumbertotal)

This creates a number filter for the 'total' field.

- `placeholders('Min Total', 'Max Total')`: Sets the placeholder text for the minimum and maximum input fields.

#### Filter::boolean('invoiced')

[](#filterbooleaninvoiced)

This creates a boolean filter for the 'invoiced' field.

- `labels('Yes', 'No')`: Sets the labels for the true and false values.

#### Filter::datepicker('created\_at')

[](#filterdatepickercreated_at)

This creates a date picker filter for the 'created\_at' field.

- `addDataAttribute('format', 'H:i')`: Sets a data attribute for the date picker. In this case, it's used to set the date format.

#### Filter::datetimepicker('updated\_at')

[](#filterdatetimepickerupdated_at)

This creates a datetime picker filter for the 'updated\_at' field. The datetime picker uses the user's local date and time format.

#### Filter Column Types

[](#filter-column-types)

Filters should be used with the appropriate database column types.

- `text`: VARCHAR or TEXT
- `number`: INT, FLOAT, DOUBLE, or DECIMAL
- `select`: Any type, as long as the value is a set of options
- `multiselect`: Any type, as long as the value is a set of options
- `boolean`: TINYINT(1), where 0 is false and 1 is true
- `timepicker`: TIME
- `datepicker`: DATE
- `datetimepicker`: DATETIME

### Mass Actions.

[](#mass-actions)

Mass or bulk actions provide the capability to execute operations on multiple rows of data simultaneously.

> You can group actions together using the `group` and `groupBy` helper methods.

```
use TomShaw\ElectricGrid\{Component, Column, Filter, Action};
use App\Enums\OrderStatus;

class OrdersTable extends Component
{
    public bool $showCheckbox = true;

    public function actions(): array
    {
        return [
            Action::make('approved', 'Mark Approved')
                ->group('Status Options')
                ->callback(fn ($status, $selected) => $this->updateStatusHandler($status, $selected)),

            Action::make('completed', 'Mark Completed')
                ->group('Status Options')
                ->callback(fn ($status, $selected) => $this->updateStatusHandler($status, $selected)),

            Action::make('cancelled', 'Mark Canceled')
                ->group('Status Options')
                ->callback(fn ($status, $selected) => $this->updateStatusHandler($status, $selected)),
        ];
    }

    public function updateStatusHandler(string $status, array $selectedItems)
    {
        $status = OrderStatus::fromName($status);

        foreach ($selectedItems as $index => $orderId) {
            event(new OrderStatusEvent($status->value, $orderId));
        }
    }
}
```

### Table Exports.

[](#table-exports)

Tables can be exported in the following formats `xlsx`, `csv`, `pdf`, `html`. The type of export is decided by `Extension-based format determination`. If you supply a file name of `SalesOrders.xlsx` an Excel spreadsheet will be generated.

```
use TomShaw\ElectricGrid\{Component, Column, Filter, Action};
use App\Enums\OrderStatus;

class OrdersTable extends Component
{
    public bool $showCheckbox = true;

    public function actions(): array
    {
        return [
            Action::groupBy('Export Options', function () {
                return [
                    Action::make('csv', 'Export CSV')->export('SalesOrders.csv'),
                    Action::make('pdf', 'Export PDF')->export('SalesOrders.pdf'),
                    Action::make('html', 'Export HTML')->export('SalesOrders.html'),
                    Action::make('xlsx', 'Export XLSX')->export('SalesOrders.xlsx'),
                ];
            }),
        ];
    }
}
```

Custom Excel Exports
--------------------

[](#custom-excel-exports)

Excel exports can be customized with specific styles and column widths.

Uses the `styles` and `columnWidths` methods to apply custom styles and column widths to the Excel file.

The `styles` method returns an array of cell styles. The array keys are cell references and the values are arrays of style definitions. For example, `'1'  => ['font' => ['bold' => true]]` applies a bold font style to all cells in row 1, and `'B2' => ['font' => ['italic' => true]]` applies an italic font style to the cell at column B, row 2.

The `columnWidths` method returns an array of column widths. The array keys are column letters and the values are the widths of the columns. For example, `'A' => 20` sets the width of column A to 20.

Here's an example of how to define custom styles and column widths for Excel exports:

```
    public function actions(): array
    {
        return [
            Action::groupBy('Export Options', function () {
                return [
                    Action::make('xlsx', 'Export XLSX')
                        ->export('SalesOrders.xlsx')
                        ->styles($this->exportStyles)
                        ->columnWidths($this->exportWidths),
                ];
            }),
        ];
    }

    public function getExportStylesProperty()
    {
        return [
            '1'  => ['font' => ['bold' => true]],
            'B2' => ['font' => ['italic' => true]],
            'C'  => ['font' => ['size' => 16]],
        ];
    }

    public function getExportWidthsProperty()
    {
        return [
            'A' => 20,
            'B' => 30,
        ];
    }
```

### Export Callbacks

[](#export-callbacks)

When using HTML callbacks for display (e.g., Blade views for badges, buttons, or formatted content), you may want different output for exports. The `exportCallback` method allows you to specify how a column's data should be formatted when exported, separate from how it's displayed in the grid.

#### The Problem

[](#the-problem)

If you use a callback that returns HTML for display:

```
Column::add('status', 'Status')
    ->callback(fn (Order $order) => view('components.status-badge', ['status' => $order->status]))
    ->exportable()
```

The exported file would contain raw HTML like `Active` instead of just `Active`.

#### The Solution

[](#the-solution)

Use `exportCallback` to define export-specific formatting:

```
Column::add('status', 'Status')
    ->callback(fn (Order $order) => view('components.status-badge', ['status' => $order->status]))
    ->exportCallback(fn (Order $order) => $order->status)
    ->exportable()
```

Now the grid displays the styled badge, while exports contain the clean value.

#### Behavior

[](#behavior)

- **With `exportCallback` set**: Exports use the export callback
- **Without `exportCallback`**: Exports use the raw database value

This means you don't need to specify `exportCallback` if you just want the raw value - simply omit it:

```
// Display: HTML badge | Export: raw database value
Column::add('status', 'Status')
    ->callback(fn (Order $order) => view('components.status-badge', ['status' => $order->status]))
    ->exportable()

// Display: formatted date | Export: custom date format
Column::add('created_at', 'Created At')
    ->callback(fn (Order $order) => view('components.date-display', ['date' => $order->created_at]))
    ->exportCallback(fn (Order $order) => $order->created_at->format('Y-m-d H:i:s'))
    ->exportable()

// Display: currency format | Export: same currency format
Column::add('total', 'Total')
    ->callback(fn (Order $order) => number_format($order->total, 2))
    ->exportCallback(fn (Order $order) => number_format($order->total, 2))
    ->exportable()
```

### Search Input

[](#search-input)

Enable by adding the following property filled with the columns names you wish to search.

```
public array $searchTermColumns = ['title', 'description'];
```

### Letter Search

[](#letter-search)

Enable by adding the following property filled with the columns names you wish to search.

```
public array $letterSearchColumns = ['name'];
```

### Pagination &amp; Per-Page Controls

[](#pagination--per-page-controls)

Electric Grid includes intelligent per-page pagination controls that automatically adapt based on your dataset size.

#### Default Behavior

[](#default-behavior)

By default, the grid displays 15 records per page with the following options available:

```
public int $perPage = 15;
public array $perPageValues = [15, 30, 50, 100];
```

The per-page selector automatically:

- **Hides when not needed** (no records or records ≤ minimum value)
- **Filters out irrelevant options** (removes values ≥ total records)
- **Shows only when useful** (requires more records than smallest per-page option)

#### Customizing Per-Page Options

[](#customizing-per-page-options)

Override the per-page values in your component:

```
class OrdersTable extends Component
{
    public int $perPage = 25;
    public array $perPageValues = [25, 50, 100, 250];
}
```

#### "Show All" Option

[](#show-all-option)

The "All" option displays all records on a single page, but includes smart safeguards:

```
public bool $showAllOption = true;        // Enable/disable "All" option
public int $showAllThreshold = 1000;      // Hide "All" if records exceed this
```

The "All" option automatically hides when:

- Total records exceed the `showAllThreshold`
- The `showAllOption` property is set to `false`
- There are no records in the dataset

Example with custom threshold:

```
class OrdersTable extends Component
{
    public int $showAllThreshold = 500;  // Only show "All" for datasets under 500 records
}
```

#### Hiding the Per-Page Selector

[](#hiding-the-per-page-selector)

Completely disable the per-page selector:

```
public bool $showPerPage = false;
```

#### Global Configuration

[](#global-configuration)

You can set global defaults by publishing and modifying the config file:

```
php artisan vendor:publish --tag=electricgrid.config
```

Then edit `config/electricgrid.php`:

```
'per_page' => [
    'default' => 15,
    'values' => [15, 30, 50, 100],
    'show_all' => true,
    'show_all_threshold' => 1000,
],
```

#### Session Persistence

[](#session-persistence)

Per-page settings are automatically saved to the session when `persistFilters` is enabled:

```
class OrdersTable extends Component
{
    public bool $persistFilters = true;  // Remembers user's per-page selection
}
```

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

[](#requirements)

The package is compatible with Laravel 12+ and PHP 8.5.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

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

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

[](#contributing)

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

License
-------

[](#license)

The MIT License (MIT). See [License File](LICENSE) for more information.

###  Health Score

56

—

FairBetter than 98% of packages

Maintenance89

Actively maintained with recent releases

Popularity33

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity74

Established project with proven stability

 Bus Factor1

Top contributor holds 98.3% 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 ~11 days

Total

68

Last Release

56d ago

Major Versions

v0.5.2 → v1.0.02025-03-12

v1.5.1 → v2.0.02026-01-22

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

v0.3.0PHP ^8.2

v0.5.1PHP ^8.1|^8.2|^8.3|^8.4

v0.5.2PHP ^8.2|^8.3|^8.4

v1.4.0PHP ^8.2|^8.3|^8.4|^8.5

### Community

Maintainers

![](https://www.gravatar.com/avatar/14fd02efdbaf6247b61c9846697c86dabcbf430374aeff0d80e509d95d186658?d=identicon)[Tom Shaw](/maintainers/Tom%20Shaw)

---

Top Contributors

[![tomshaw](https://avatars.githubusercontent.com/u/32818?v=4)](https://github.com/tomshaw "tomshaw (227 commits)")[![dependabot[bot]](https://avatars.githubusercontent.com/in/29110?v=4)](https://github.com/dependabot[bot] "dependabot[bot] (4 commits)")

---

Tags

laravellivewirelaravelgridlivewiredatagridtabledatatable

###  Code Quality

TestsPest

Static AnalysisPHPStan

Code StyleLaravel Pint

### Embed Badge

![Health badge](/badges/tomshaw-electricgrid/health.svg)

```
[![Health](https://phpackages.com/badges/tomshaw-electricgrid/health.svg)](https://phpackages.com/packages/tomshaw-electricgrid)
```

###  Alternatives

[livewire/flux

The official UI component library for Livewire.

9475.0M86](/packages/livewire-flux)[livewire/volt

An elegantly crafted functional API for Laravel Livewire.

4205.3M84](/packages/livewire-volt)[spatie/laravel-livewire-wizard

Build wizards using Livewire

4061.0M4](/packages/spatie-laravel-livewire-wizard)[ramonrietdijk/livewire-tables

Dynamic tables for models with Laravel Livewire

21147.4k](/packages/ramonrietdijk-livewire-tables)[okipa/laravel-table

Generate tables from Eloquent models.

56752.8k](/packages/okipa-laravel-table)[aedart/athenaeum

Athenaeum is a mono repository; a collection of various PHP packages

245.2k](/packages/aedart-athenaeum)

PHPackages © 2026

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