Grid.js Integration
Grid.js Integration
UltraViolet Pro includes Grid.js, a powerful and lightweight table library that provides advanced data grid functionality with sorting, filtering, pagination, and more.
Overview
Grid.js is a framework-agnostic table library built with TypeScript. It offers:
- Lightweight: Minimal bundle size with maximum functionality
- Framework Agnostic: Works with any JavaScript framework or vanilla JS
- TypeScript Support: Built with TypeScript for better development experience
- Extensible: Plugin system for custom functionality
- Responsive: Mobile-friendly design out of the box
Basic Usage
HTML Setup
<!-- Include Grid.js -->
<script src="https://cdn.jsdelivr.net/npm/gridjs@6.0.6/dist/gridjs.umd.js"></script>
<link href="https://cdn.jsdelivr.net/npm/gridjs@6.0.6/dist/mermaid.min.css" rel="stylesheet" />
<!-- Create container -->
<div id="wrapper"></div>
JavaScript Initialization
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Phone Number", "Position"],
data: [
["John", "john@example.com", "(353) 01 222 3333", "Software Engineer"],
["Mark", "mark@gmail.com", "(01) 22 888 4444", "Data Scientist"],
["Eoin", "eoin@gmail.com", "0097 22 654 00033", "Web Developer"]
]
}).render(document.getElementById("wrapper"));
Advanced Configuration
With Search and Pagination
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Phone Number", "Position"],
data: [
["John", "john@example.com", "(353) 01 222 3333", "Software Engineer"],
["Mark", "mark@gmail.com", "(01) 22 888 4444", "Data Scientist"],
["Eoin", "eoin@gmail.com", "0097 22 654 00033", "Web Developer"]
],
search: true,
pagination: {
limit: 5
},
sort: true,
resizable: true,
fixedHeader: true,
height: '400px'
}).render(document.getElementById("wrapper"));
Custom Cell Renderers
const grid = new gridjs.Grid({
columns: [
"Name",
"Email",
"Status",
{
name: "Actions",
formatter: (cell, row) => {
return gridjs.html(`
<button class="btn btn-sm btn-primary me-2" onclick="editUser(${row.cells[0].data})">Edit</button>
<button class="btn btn-sm btn-danger" onclick="deleteUser(${row.cells[0].data})">Delete</button>
`);
}
}
],
data: [
["John", "john@example.com", "Active"],
["Mark", "mark@gmail.com", "Inactive"],
["Eoin", "eoin@gmail.com", "Active"]
]
}).render(document.getElementById("wrapper"));
Server-Side Data
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Position"],
server: {
url: '/api/users',
then: data => data.users,
total: data => data.total
},
search: {
server: {
url: (prev, keyword) => `${prev}?search=${keyword}`
}
},
pagination: {
server: {
url: (prev, page, limit) => `${prev}?page=${page}&limit=${limit}`
}
}
}).render(document.getElementById("wrapper"));
Styling and Theming
Custom CSS Classes
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Position"],
data: [
["John", "john@example.com", "Software Engineer"],
["Mark", "mark@gmail.com", "Data Scientist"]
],
className: {
table: 'table table-striped table-bordered',
thead: 'table-dark',
tbody: 'table-hover'
}
}).render(document.getElementById("wrapper"));
Bootstrap Integration
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Position"],
data: [
["John", "john@example.com", "Software Engineer"],
["Mark", "mark@gmail.com", "Data Scientist"]
],
className: {
container: 'table-responsive',
table: 'table table-striped table-bordered',
thead: 'table-dark',
tbody: 'table-hover',
th: 'text-center',
td: 'text-center'
},
style: {
container: 'margin-top: 20px;',
table: 'margin-bottom: 0;'
}
}).render(document.getElementById("wrapper"));
Export Functionality
CSV Export
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Position"],
data: [
["John", "john@example.com", "Software Engineer"],
["Mark", "mark@gmail.com", "Data Scientist"]
],
plugins: [gridjs.plugin.excel()]
}).render(document.getElementById("wrapper"));
Custom Export Button
<button id="exportBtn" class="btn btn-success">Export to CSV</button>
<div id="wrapper"></div>
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Position"],
data: [
["John", "john@example.com", "Software Engineer"],
["Mark", "mark@gmail.com", "Data Scientist"]
]
}).render(document.getElementById("wrapper"));
document.getElementById("exportBtn").addEventListener("click", () => {
grid.export("csv", "users.csv");
});
Event Handling
Row Click Events
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Position"],
data: [
["John", "john@example.com", "Software Engineer"],
["Mark", "mark@gmail.com", "Data Scientist"]
],
onRowClick: (row) => {
console.log("Row clicked:", row);
// Handle row click
}
}).render(document.getElementById("wrapper"));
Cell Click Events
const grid = new gridjs.Grid({
columns: [
"Name",
"Email",
{
name: "Position",
formatter: (cell) => {
return gridjs.html(`<span class="clickable-cell">${cell}</span>`);
}
}
],
data: [
["John", "john@example.com", "Software Engineer"],
["Mark", "mark@gmail.com", "Data Scientist"]
]
}).render(document.getElementById("wrapper"));
// Add click listener after render
document.addEventListener("click", (e) => {
if (e.target.classList.contains("clickable-cell")) {
console.log("Cell clicked:", e.target.textContent);
}
});
Integration with Laravel
Controller Method
class UserController extends Controller
{
public function index(Request $request)
{
$query = User::query();
// Handle search
if ($request->has('search')) {
$search = $request->get('search');
$query->where(function($q) use ($search) {
$q->where('name', 'like', "%{$search}%")
->orWhere('email', 'like', "%{$search}%")
->orWhere('position', 'like', "%{$search}%");
});
}
// Handle pagination
$page = $request->get('page', 1);
$limit = $request->get('limit', 10);
$offset = ($page - 1) * $limit;
$users = $query->offset($offset)->limit($limit)->get();
$total = $query->count();
return response()->json([
'users' => $users,
'total' => $total
]);
}
}
Frontend Integration
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Position"],
server: {
url: '/api/users',
then: data => data.users.map(user => [user.name, user.email, user.position]),
total: data => data.total
},
search: {
server: {
url: (prev, keyword) => `${prev}?search=${keyword}`
}
},
pagination: {
server: {
url: (prev, page, limit) => `${prev}?page=${page}&limit=${limit}`
}
}
}).render(document.getElementById("wrapper"));
Best Practices
- Performance: Use server-side processing for large datasets
- Responsive Design: Always wrap Grid.js in responsive containers
- Accessibility: Include proper ARIA labels and keyboard navigation
- Error Handling: Implement proper error handling for server requests
- Loading States: Show loading indicators during data fetching
- Memory Management: Destroy grid instances when components are unmounted
Troubleshooting
Common Issues
- Styling Conflicts: Ensure Bootstrap CSS is loaded before Grid.js CSS
- JavaScript Errors: Check browser console for initialization errors
- Data Loading: Verify API endpoints return data in expected format
- Search Issues: Ensure search parameters are properly handled on server-side
Debug Mode
const grid = new gridjs.Grid({
columns: ["Name", "Email", "Position"],
data: [
["John", "john@example.com", "Software Engineer"]
],
debug: true // Enable debug mode
}).render(document.getElementById("wrapper"));
Examples in UltraViolet
Grid.js is used in several places throughout UltraViolet:
- Tables Overview: Demonstrates basic Grid.js functionality
- JS Grid Page: Advanced examples with custom renderers
- User Management: Server-side data with search and pagination
- Reports: Export functionality for data tables
For more examples, check the resources/views/admin/tables/ directory.