@maxpoletto/sortable-table
v1.3.0
Published
A reusable, configurable table component with sorting, filtering, and pagination
Maintainers
Readme
SortableTable
A reusable and configurable sortable table component with good pagination and theming support.
Features
Sorting
- Multi-type sorting (string, number, date, boolean), ascending/descending order
- Visual sort indicators with smooth transitions
Navigation
- Navigation controls: First (
<<), Previous (<), Next (>), Last (>>) buttons, disabled when not applicable - Editable page number: click the current page number to jump to any page, press Enter to confirm, Escape to cancel
- Configurable page sizes
- Localizable page indicator via the
pageInfotemplate option
Customization
- CSS custom properties for easy theming
- A few built-in themes (compact, spacious, minimal, bordered, solid)
- Custom formatter functions
- HTML-safe rendering by default, with explicit trusted HTML opt-in
- Responsive design with mobile-optimized layouts
Efficiency
- Memory efficient: data is represented as an array of arrays
- Limited DOM manipulation (only updates visible rows)
Quick Start
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="sortable-table.css">
</head>
<body>
<div id="my-table"></div>
<script src="sortable-table.js"></script>
<script>
const columns = [
{ key: 'id', label: 'ID', type: 'number' },
{ key: 'name', label: 'Name', type: 'string' },
{ key: 'salary', label: 'Salary', type: 'number',
formatter: (value) => `$${value.toLocaleString()}` },
{ key: 'startDate', label: 'Start Date', type: 'date' }
];
const data = [
[1, 'John Doe', 75000, new Date('2020-01-15')],
[2, 'Jane Smith', 85000, new Date('2019-03-20')]
];
const table = new SortableTable({
container: '#my-table',
data: data,
columns: columns,
rowsPerPage: 25
});
</script>
</body>
</html>Configuration Options
Constructor
const table = new SortableTable({
// Required
container: '#table-container', // Element or selector
data: [...], // Array of arrays (one array per row)
columns: [...], // Column definitions (see below)
// Optional
rowsPerPage: 25, // Rows per page (default: 25)
showPagination: true, // Show pagination controls (default: true)
allowSorting: true, // Allow column sorting (default: true)
cssPrefix: 'sortable-table', // CSS class prefix (default: 'sortable-table')
emptyMessage: 'No data available', // Message when no data (default: 'No data available')
pageInfo: 'Page {current} of {total}', // Pagination text; include both
// {current}/{total}, each replaced once
// with the page-number controls
// (default: 'Page {current} of {total}')
sort: { column: 'name', ascending: true }, // Initial sort
// Event callbacks
onSort: (column, ascending) => {...}, // Called when sorted
onPageChange: (page, totalPages) => {...}, // Called when page changes
onRowClick: (data, index, event) => {...} // Called when row is clicked
});Column Definition
const columns = [
{
key: 'fieldName', // Data field name or function
label: 'Display Name', // Column header text
type: 'string', // 'string', 'number', 'date', 'boolean'
width: '120px', // Optional: column width
hidden: false, // Optional: hide column (default: false)
sortable: true, // Optional: allow sorting (default: true)
className: 'custom-class', // Optional: custom header CSS class
cellClassName: 'cell-class', // Optional: custom cell CSS class
formatter: (value, row) => { // Optional: custom formatter function
return `$${value.toLocaleString()}`;
},
trustedHTML: false // Optional: render formatter output as
// raw HTML only when explicitly true
}
];Formatter return values are escaped and rendered as text by default. Set trustedHTML: true only for columns whose formatter returns application-controlled markup, such as action buttons or icons. Do not enable it for user-entered data.
API Methods
Data Management
// Update all data
table.setData(newDataArray);
// Add a single row
table.addRow(rowData);
// Remove rows that match the predicate
table.removeRows(predicate);
// Sort by column in ascending or descending order
table.sort(key, type, ascending);
// Toggle sort order by column
// (if key denotes the current sort column, else sort by that column in ascending order)
table.toggleSort(key, type);
// Filter data (creates a view, doesn't modify original)
table.filter(row => row.salary > 50000);
// Clear all filters
table.clearFilter();Navigation
// Go to specific page
table.goToPage(pageNumber);
// Get current page data
const currentData = table.getVisibleData();Cleanup
// Destroy table and clean up event listeners
table.destroy();Theming
CSS Custom Properties
:root {
--st-primary-color: #2196F3; /* Accent color */
--st-border-color: #ddd; /* Border color */
--st-header-bg: #f7f7f7; /* Header background */
--st-hover-bg: #f9f9f9; /* Row hover background */
--st-font-size: 13px; /* Base font size */
--st-padding: 8px; /* Base padding */
--st-border-radius: 4px; /* Border radius for buttons and container, */
}Built-in Theme Classes
<!-- Compact theme -->
<div id="table" class="theme-compact"></div>
<!-- Spacious theme -->
<div id="table" class="theme-spacious"></div>
<!-- Minimal theme (no borders) -->
<div id="table" class="theme-minimal"></div>
<!-- Bordered cells -->
<div id="table" class="theme-bordered"></div>
<!-- Solid rows (no striping) -->
<div id="table" class="theme-solid"></div>Examples: a basic employee table
const employees = [
[1, 'Alice Johnson', 'Engineering', 95000, true],
[2, 'Bob Smith', 'Marketing', 75000, true]
];
const table = new SortableTable({
container: '#employee-table',
data: employees,
columns: [
{ key: 'id', label: 'ID', type: 'number', width: '60px' },
{ key: 'name', label: 'Name', type: 'string' },
{ key: 'department', label: 'Department', type: 'string' },
{ key: 'salary', label: 'Salary', type: 'number',
formatter: (value) => `$${value.toLocaleString()}` },
{ key: 'active', label: 'Status', type: 'boolean',
formatter: (value) => value ? '✅ Active' : '❌ Inactive' }
],
rowsPerPage: 20,
onRowClick: (employee) => {
alert(`Employee: ${employee[1]}\nSalary: $${employee[3].toLocaleString()}`);
}
});Browser Support
Tested on modern versions of Chrome, Firefox, Safari, and Edge. Technically should work with:
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
Files
- src/sortable-table.js - Main table component
- src/sortable-table.css - Styles and themes
- demo/demo.html - Interactive demo page
- test/sortable-table.test.html - Tests
To run demo or tests, run make test-server and open http://localhost:8000 in your browser.
