rafwell/laravel-simplegrid
rafwell/laravel-simplegrid is a lightweight Laravel package for building simple, customizable data grids. Render sortable, searchable, paginated tables with minimal configuration, ideal for admin panels and CRUD listings.
composer require rafwell/laravel-simplegrid. Laravel ≥5.5 auto-discovers the service provider; no migrations or required config.use Rafwell\Simplegrid\Grid;
public function index()
{
$grid = new Grid(User::class, 'users-grid');
$grid->query(User::query());
$grid->fields([
'id' => 'ID',
'name' => 'Name',
'email' => 'Email',
'created_at' => 'Created',
]);
return view('users.index', compact('grid'));
}
{{-- users/index.blade.php --}}
{!! $grid->render() !!}
Where to look first
README.md — the de-facto API reference.src/Grid.php (and sibling classes) — authoritative method list; docs lag behind code on small packages.resources/views/ — the Blade template the package renders; publish or override if the markup needs to match your layout.One Grid class per resource (recommended)
Wrap each list view in a dedicated class — typically under app/Grids/ — extending Rafwell\Simplegrid\Grid. This centralises fields, actions, filter hooks, and default ordering, and lets you reuse the same grid on a dashboard and a full index page. Keep the controller thin: build the query, inject scopes, render.
Customising field output
Field definitions usually accept either a plain label or an array with a render closure. Use the closure for:
$row->created_at->format('d/m/Y'))route('users.show', $row->id))$grid->fields([
'name' => [
'label' => 'User',
'render' => fn($row) => '<strong>'.e($row->name).'</strong>',
],
'status' => [
'label' => 'Status',
'render' => fn($row) => $row->active
? '<span class="badge bg-success">Active</span>'
: '<span class="badge bg-secondary">Inactive</span>',
],
]);
Relations and computed columns
Eager-load anything a render callback touches (User::with('profile', 'roles')). Sorting on related/computed columns requires a join + select alias in the base query — accessor-only attributes cannot be ORDER BY server-side.
Row actions
Wire per-row Edit / Delete buttons through the grid's action API (or a render closure that outputs an inline form). For deletes, always use a real <form> with @csrf and @method('DELETE'); a GET link will bypass CSRF.
Search and sort
LIKE '%term%' on a large unindexed table is the usual performance cliff.Filters
$grid->query(User::where('tenant_id', auth()->id())).Blade integration
render() returns HTML/HtmlString; always {!! !!}.render() output is inserted raw. Escape user-controlled values inside callbacks with e(), or you reintroduce XSS.column, table, or SQL snippets.render/action closure must be eager-loaded. Watch DB::listen the first time you render a grid.->appends(request()->query()), or filters disappear on page 2.orderBy (ideally on the primary key), rows can shuffle between pages on large tables.@method('DELETE') + @csrf; a plain link silently fails or, worse, deletes via GET.composer.json, check Grid.php when the README looks stale, and test after every Laravel upgrade — Blade views and method signatures can shift between minors.->toSql()), field keys match real attributes, and render() is being echoed with {!! !!} — a silent {{ }} is the most common "broken grid".Grid, override field/query setup, and reuse the base for consistent styling. Publish the Blade view for markup changes rather than forking the package.perPage, and prefer select() with only the columns you display.How can I help you explore Laravel packages today?