drago-ex/datagrid
Composer 安装命令:
composer require drago-ex/datagrid
包简介
A simple datagrid for sorting and filtering data.
README 文档
README
Drago DataGrid is a powerful and extendable tabular data component built on top of the Nette Framework. It provides high-performance filtering, sorting, pagination, and row actions with flexible Latte templates for rendering Bootstrap 5 styled tables.
Requirements
- PHP >= 8.3
- Nette Framework
- Dibi
- Latte
- Bootstrap
- Naja
- Composer
Installation
composer require drago-ex/datagrid
Frontend Assets
Since the package is installed via Composer, add the following to your package.json to make the drago-datagrid alias available in your bundler:
{
"type": "module",
"dependencies": {
"drago-datagrid": "file:vendor/drago-ex/datagrid"
}
}
Then run:
npm install
After that, you can import the assets directly from the Composer-installed package:
import naja from 'naja'; import DataGrid from 'drago-datagrid'; naja.initialize(); new DataGrid().initialize(naja);
The main package entrypoint loads both required JS handlers and the shared SCSS for you. Bootstrap is still required in your app because the Latte templates are built on Bootstrap 5, but its installation stays under your control.
If you explicitly want only one feature, use the dedicated entrypoints:
import DataGridFilter from 'drago-datagrid/datagrid-filter'; import DataGridPage from 'drago-datagrid/page-items'; import 'drago-datagrid/styles/datagrid';
Features
- Text & Date Filtering - LIKE operator with SQL injection protection
- Column Sorting - Click headers to sort, toggle ASC/DESC
- Smart Pagination - LIMIT/OFFSET at DB level (5.8x faster for large datasets)
- Row Actions - Edit, Delete, or custom actions with callbacks
- Custom Formatting - Format cell values with auto-escaping
- Built-in Security - SQL injection & XSS protection by default
- AJAX Integration - Seamless Naja support, no page reload
- Bootstrap 5 - Beautiful responsive styling
Quick Start
1. Create Component in Presenter
use Drago\Datagrid\DataGrid; use Dibi\Connection; class UserPresenter extends Presenter { public function __construct(private Connection $db) {} // Create the grid component protected function createComponentGrid(): DataGrid { $grid = new DataGrid; // Set data source (Dibi Fluent query) $grid->setDataSource($this->db->select('*')->from('users')); // Add columns to display $grid->addColumnText('name', 'Name'); $grid->addColumnText('email', 'Email'); $grid->addColumnDate('created_at', 'Created', format: 'Y-m-d H:i'); return $grid; } }
2. Render in Template
{control grid}
That's it! You have a working data grid with sorting and pagination.
Building Your DataGrid
Step 1: Set Data Source
$grid = new DataGrid; $grid->setDataSource($this->db->select('*')->from('products'));
The data source must be a Dibi\Fluent query object. The grid will apply filtering, sorting, and pagination to it automatically.
Step 2: Add Columns
Define what columns to display:
// Text column (sortable by default) $grid->addColumnText('name', 'Product Name'); // Text column without sorting $grid->addColumnText('sku', 'SKU', sortable: false); // Date column with custom format $grid->addColumnDate('updated_at', 'Last Updated', format: 'd.m.Y');
Column Parameters:
name- Database column namelabel- Header label shown to usersortable- Enable click-to-sort (default: true)formatter- Optional callback to format cell values (optional)
Step 3: Add Filters (Optional)
Enable filtering on specific columns:
$grid->addColumnText('name', 'Product Name') ->setFilterText(); // Allows user to search by name $grid->addColumnText('category', 'Category') ->setFilterText(); // LIKE search $grid->addColumnDate('created_at', 'Created') ->setFilterDate(); // Date range filter (YYYY-MM-DD format)
Filter Types:
setFilterText()- LIKE search with SQL injection protectionsetFilterDate()- Single date or date range (YYYY-MM-DD or YYYY-MM-DD|YYYY-MM-DD)
Step 4: Add Row Actions (Optional)
Add Edit/Delete buttons for each row:
// First, set primary key (required for actions) $grid->setPrimaryKey('id'); // Add action buttons $grid->addAction('Edit', 'edit', 'btn btn-sm btn-primary', function($id) { $this->redirect('edit', $id); }); $grid->addAction('Delete', 'delete', 'btn btn-sm btn-danger', function($id) { $this->db->table('products')->get($id)->delete(); $this->redirect('this'); });
Action Parameters:
label- Button textsignal- Signal name (internal identifier)class- CSS classes for stylingcallback- Function executed when clicked, receives row ID
Formatting Cell Values
Simple Formatting
Format cell output (automatically escaped):
$grid->addColumnText('status', 'Status', formatter: function($value, $row) { return match($value) { 'active' => 'âś“ Active', 'inactive' => 'âś— Inactive', default => 'Unknown' }; }); $grid->addColumnText('price', 'Price', formatter: function($value, $row) { return number_format((float)$value, 2) . ' CZK'; });
With Full Row Data
Formatters receive the entire row, so you can use related data:
$grid->addColumnText('author_name', 'Author', formatter: function($value, $row) { return $row['author_name'] . ' (' . $row['author_email'] . ')'; });
Custom Date Formatting
// Date column with formatter $grid->addColumnDate('created_at', 'Created', format: 'Y-m-d', formatter: function($value, $row) { // $value is already formatted (Y-m-d), add time info return $value . ' (' . date('H:i', strtotime($row['created_at'])) . ')'; } );
Complete Example
use Drago\Datagrid\DataGrid; use Dibi\Connection; class UserPresenter extends Presenter { public function __construct(private Connection $db) {} protected function createComponentUserGrid(): DataGrid { $grid = new DataGrid; // Data source - Dibi Fluent query $grid->setDataSource($this->db->select('*')->from('users')); // Columns with filters $grid->addColumnText('name', 'Name') ->setFilterText(); $grid->addColumnText('email', 'Email') ->setFilterText(); $grid->addColumnDate('created_at', 'Registered', format: 'd.m.Y') ->setFilterDate(); // Custom formatting $grid->addColumnText('status', 'Status', formatter: function($value, $row) { return $value === 'active' ? 'âś“ Active' : 'âś— Inactive'; }); // Actions (requires primary key) $grid->setPrimaryKey('id') ->addAction('Edit', 'edit', 'btn btn-sm btn-primary', fn($id) => $this->editUser($id)) ->addAction('Delete', 'delete', 'btn btn-sm btn-danger', fn($id) => $this->deleteUser($id)); return $grid; } private function editUser($id): void { // Your edit logic... } private function deleteUser($id): void { // Your delete logic... } }
Security
Auto-Escaping Protection
All cell values and formatter output are automatically HTML-escaped to prevent XSS attacks. This is enabled by default and cannot be disabled for regular columns.
// Safe - automatically escaped $grid->addColumnText('description', 'Description', formatter: function($value) { return strtoupper($value); // Output will be escaped });
SQL Injection Protection
- Text and date filters use parameterized queries via Dibi
- Special characters (
%,_) in LIKE searches are properly escaped - Date filters validate format before executing query
Other Protections
- Primary Key Validation - Primary key existence is checked before rendering actions
- CSRF Protection - Handled automatically by Nette Framework
- Input Validation - Date filter validates YYYY-MM-DD format
统计信息
- 总下载量: 27
- 月度下载量: 0
- 日度下载量: 0
- 收藏数: 0
- 点击次数: 3
- 依赖项目数: 1
- 推荐数: 0
其他信息
- 授权协议: MIT
- 更新时间: 2026-02-20