Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Datagrid Laravel Package

fsi/datagrid

FSI DataGrid is a Laravel package for building configurable data grids. Define columns, filters, sorting, pagination and row actions in PHP, then render sortable, searchable tables with minimal code.

View on GitHub
Deep Wiki
Context7

Getting Started

Treat fsi/datagrid as a standalone PHP presentation component, not a Laravel package. It has no Laravel service provider, facade, Blade directives, config file, or auto-discovery. You are wiring it into Laravel yourself.

Version 2.1.0 makes this materially more viable on a modern Laravel stack than earlier releases: it allows PHP 8, drops doctrine/persistence below 1.3, and drops Symfony 2.x components in favor of some Symfony 5.x components. That maps roughly onto Laravel 8/9-era dependency graphs. It is still not Laravel-native, and there is no indication of testing beyond the PHP 8.0/8.1 window.

Minimal path:

  1. Install and inspect:

    composer require fsi/datagrid
    

    Look first at:

    • README.md and CHANGELOG.md
    • composer.json (check the exact php, symfony/*, and doctrine/persistence constraints)
    • src/DataGridFactoryBuilder.php / src/DataGridFactory.php
    • src/Column/
    • src/DataSource/
    • tests for the exact factory, column, and view API in the installed version
  2. Bind the factory once in a service provider:

    use FSi\Component\DataGrid\DataGridFactory;
    use FSi\Component\DataGrid\DataGridFactoryBuilder;
    
    public function register(): void
    {
        $this->app->singleton(DataGridFactory::class, function () {
            return DataGridFactoryBuilder::build();
        });
    }
    
  3. First useful use case: a read-only admin listing from an array or already-loaded Eloquent collection.

    $grid = $factory->createDataGrid('users');
    
    $grid->addColumn('id', 'number', ['label' => 'ID']);
    $grid->addColumn('name', 'text', ['label' => 'Name']);
    $grid->addColumn('email', 'text', ['label' => 'Email']);
    $grid->addColumn('created_at', 'datetime', ['label' => 'Created']);
    
    $grid->setData(new ArrayDataSource(
        User::query()->latest()->limit(50)->get()->toArray()
    ));
    
    $view = $grid->createView();
    
    return view('admin.users.index', ['grid' => $view]);
    
  4. Render manually in Blade. There is no package-provided Laravel table renderer; iterate the view’s columns and rows and escape output with Blade {{ }}.

Use this package only if you need its column-object abstraction. For a new Laravel CRUD screen, a simple Blade table or a maintained Laravel table package is usually less work.

Implementation Patterns

Keep one grid definition class per listing.
Put grid configuration in app/DataGrids/UserGrid.php or similar. Inject the shared DataGridFactory, build columns there, and return the view. This keeps controllers small and makes column changes reviewable.

final class UserGrid
{
    public function __construct(private DataGridFactory $factory) {}

    public function view(Collection $users): mixed
    {
        $grid = $this->factory->createDataGrid('users');
        $grid->addColumn('id', 'number', ['label' => 'ID']);
        $grid->addColumn('name', 'text', ['label' => 'Name']);
        $grid->addColumn('email', 'text', ['label' => 'Email']);
        $grid->setData(new ArrayDataSource($users->toArray()));

        return $grid->createView();
    }
}

Adapt Eloquent through a data source boundary.
The package expects a data source, not an Eloquent builder. The simplest reliable pattern is to paginate/filter/sort in Laravel first, then pass the resulting rows as arrays to ArrayDataSource. For larger datasets, write a custom data source implementing the package’s DataSourceInterface and normalize models into the row shape your columns expect.

Do query concerns outside the grid.
Treat fsi/datagrid as a renderer, not a query layer. Handle:

  • pagination with Laravel’s paginator
  • sorting with orderBy() based on validated request parameters
  • filtering with query scopes
  • authorization with policies or gates
  • relationship loading with with() to avoid N+1 queries

Pass only the page of rows the grid should display.

Render through a Blade partial.
Create resources/views/admin/partials/datagrid.blade.php and render labels and row values yourself. Keep escaping on:

<table>
    <thead>
        <tr>
            @foreach ($grid->getColumns() as $column)
                <th>{{ $column->getLabel() }}</th>
            @endforeach
        </tr>
    </thead>
    <tbody>
        @foreach ($grid->getRows() as $row)
            <tr>
                {{-- use the row/column API exposed by the installed version --}}
            </tr>
        @endforeach
    </tbody>
</table>

Confirm the exact view API (getColumns(), getRows(), row cell access) in the package source; it is old enough that examples online may not match your installed version — and 2.1.0 is a dependency-constraint release, not an API release, so the view layer is unchanged.

Use custom column types sparingly.
If a value needs special formatting, first try transforming the row before handing it to the grid. If you need reusable behavior across grids, register a custom column type with the factory builder/extensions during application boot. Keep custom types small and test them with ArrayDataSource.

Use ArrayDataSource for tests.
This is the easiest way to lock down column definitions and rendering behavior without a database. Assert that the grid view contains expected labels and row values.

Convert the view for APIs or Inertia if needed.
If you are not rendering HTML, iterate the grid view and map it into a plain array in a presenter or resource class. Do not leak the package’s view object into your public API response shape.

Gotchas and Tips

  • This is not a Laravel package. There is no package discovery, config publishing, facade, Blade integration, or Laravel-specific documentation. Expect to write all integration code yourself.
  • 2.1.0 is a dependency-compatibility release, not a feature release. It allows PHP 8, drops doctrine/persistence < 1.3, and drops Symfony 2.x while allowing "some" Symfony 5.x components. No new rendering API, no Laravel hooks, no deprecations to migrate. Plan for no functional change after upgrading.
  • "Allowed PHP 8" is not the same as "tested on your PHP 8." Verify the exact constraint in composer.json. Symfony 5.x components were never validated against PHP 8.3+, and this package has no CI signal for it. Smoke-test on your target runtime before adopting, and be prepared to pin if static analysis or runtime deprecations surface.
  • Low adoption and stale maintenance. With 27 stars, zero dependents, and no substantive feature work since 2021, community support is minimal. The 2.1.0 bump removes the hard install blockers but does not make it a maintained Laravel component. Prefer a Laravel-native table implementation for greenfield work.
  • Dependency resolution can still bite. Requiring doctrine/persistence >= 1.3 and specific Symfony 5.x components can conflict with what your Laravel version already pulls in, or with packages still on Doctrine 2/Symfony 6. If Composer resolution is painful, that is a strong signal not to force it into the application.
  • It is a presentation component, not a CRUD framework. It does not paginate, filter, sort, authorize, or query your database. If you pass an entire table into it, you will load everything into memory.
  • Data source shape matters. Column keys must match the row keys or object properties your data source returns. Normalize Eloquent models to arrays if the package’s column types expect array access.
  • Escaping is your responsibility. Do not render raw cell values with {!! !!} unless you have sanitized them. Use Blade escaping for user-controlled data.
  • Column type names and options are version-sensitive. Confirm text, number, datetime, and other type names in src/Column/ for the installed version. Old blog examples may target different FSi versions.
  • Factory/extensions are boot-time concerns. Register custom column types or extensions when building the factory, not midway through rendering a grid.
  • Debug with ArrayDataSource first. If a grid is blank or misaligned, replace the real data source with a small array and dump the created view. That isolates column configuration from query/data-source issues.
  • Do not rely on it for security. Enforce authorization and field visibility in your controller/policy layer. The grid will render whatever columns and rows you give it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo