TablixJS now includes a comprehensive sorting system that supports both client-side and server-side sorting with advanced features like multi-column sorting, custom sort functions, and full accessibility support.
Each column can be in one of three states:
import Table from './src/core/Table.js';
const table = new Table('#myTable', {
data: employees,
columns: [
{ name: 'name', title: 'Employee Name' },
{ name: 'age', title: 'Age', sortType: 'number' },
{ name: 'salary', title: 'Salary', sortType: 'number' },
{ name: 'department', title: 'Department' }
],
sorting: {
enabled: true,
multiColumn: true,
defaultSortType: 'auto'
}
});
columns: [
{
name: 'name',
title: 'Name',
sortable: true, // Enable/disable sorting for this column
sortType: 'string' // 'auto', 'string', 'number', 'date', 'boolean'
},
{
name: 'salary',
title: 'Salary',
sortType: 'number',
sortFunction: (a, b) => {
// Custom sort function
return parseFloat(a) - parseFloat(b);
}
},
{
name: 'joinDate',
title: 'Join Date',
sortType: 'date',
sortFunction: (a, b) => new Date(a) - new Date(b)
},
{
name: 'status',
title: 'Status',
sortable: false // Disable sorting for this column
}
]
sort(columnName, direction, addToExisting)Sort by a specific column programmatically.
// Sort by name ascending
await table.sort('name', 'asc');
// Sort by salary descending
await table.sort('salary', 'desc');
// Clear sort for a column
await table.sort('name', null);
// Multi-column sort: add to existing sorts
await table.sort('department', 'asc', false); // Primary sort
await table.sort('salary', 'desc', true); // Add secondary sort
Parameters:
columnName (string): Column to sort bydirection (string|null): 'asc', 'desc', or null for unsortedaddToExisting (boolean): Add to existing sorts vs replace alltoggleSort(columnName, addToExisting)Toggle sort state for a column (mimics header click).
// Toggle sort for name column
await table.toggleSort('name');
// Toggle with multi-column support
await table.toggleSort('salary', true);
clearSorting()Clear all sorting and return to original data order.
await table.clearSorting();
getSortState()Get current sort state information.
const sortState = table.getSortState();
console.log(sortState);
// Output: {
// sorts: [
// { column: 'department', direction: 'asc' },
// { column: 'salary', direction: 'desc' }
// ],
// mode: 'client',
// multiColumn: true
// }
sorting: {
enabled: true, // Enable/disable sorting
mode: 'client', // 'client' or 'server'
multiColumn: true, // Allow multi-column sorting
serverSortLoader: null, // Function for server-side sorting
defaultSortType: 'auto', // Default sort type
caseSensitive: false, // String comparison case sensitivity
nullsFirst: false // Put null values first or last
}
{
name: 'createdAt',
title: 'Created Date',
sortFunction: (a, b) => {
return new Date(a) - new Date(b);
}
}
{
name: 'priority',
title: 'Priority',
sortFunction: (a, b) => {
const priorities = { 'High': 3, 'Medium': 2, 'Low': 1 };
return (priorities[b] || 0) - (priorities[a] || 0);
}
}
{
name: 'version',
title: 'Version',
sortFunction: (a, b) => {
const parseVersion = (v) => v.split('.').map(n => parseInt(n) || 0);
const aVersion = parseVersion(a);
const bVersion = parseVersion(b);
for (let i = 0; i < Math.max(aVersion.length, bVersion.length); i++) {
const aPart = aVersion[i] || 0;
const bPart = bVersion[i] || 0;
if (aPart !== bPart) return aPart - bPart;
}
return 0;
}
}
table.on('beforeSort', (data) => {
console.log('About to sort:', {
columnName: data.columnName,
direction: data.direction,
addToExisting: data.addToExisting,
currentSorts: data.currentSorts
});
});
table.on('afterSort', (data) => {
console.log('Sort completed:', {
columnName: data.columnName,
direction: data.direction,
currentSorts: data.currentSorts
});
// Update external UI or save state
localStorage.setItem('tableSortState', JSON.stringify(data.currentSorts));
});
For large datasets, implement server-side sorting:
const table = new Table('#myTable', {
columns: [...],
sorting: {
enabled: true,
mode: 'server',
serverSortLoader: async (params) => {
// params contains: { sorts, filters, page, pageSize }
const response = await fetch('/api/data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(params)
});
const result = await response.json();
return {
data: result.items,
totalRows: result.totalCount
};
}
}
});
{
sorts: [
{ column: 'name', direction: 'asc' },
{ column: 'salary', direction: 'desc' }
],
filters: { department: 'Engineering' },
page: 1,
pageSize: 10
}
:root {
--tablix-sort-active-color: #007acc;
--tablix-sort-inactive-color: #ccc;
--tablix-sort-arrow-size: 12px;
--tablix-header-hover-bg: rgba(0, 0, 0, 0.05);
--tablix-sorted-header-bg: rgba(0, 122, 204, 0.05);
}
.tablix-sort-asc::before {
content: '▲';
}
.tablix-sort-desc::before {
content: '▼';
}
.tablix-sort-none {
opacity: 0.3;
}
Sorting automatically integrates with other table features:
// Sorting resets pagination to page 1
await table.sort('name', 'asc');
console.log(table.getPaginationInfo().currentPage); // 1
// Sorting works with filtered data
await table.filter({ department: 'Engineering' });
await table.sort('salary', 'desc'); // Sorts only filtered results
If updating from a basic sorting implementation:
// OLD: Basic array-based sorting
await table.sort([{ column: 'name', direction: 'asc' }]);
// NEW: Enhanced single-column sorting
await table.sort('name', 'asc');
// OLD: Manual sort state management
table.sortState = [...];
// NEW: Built-in sort state
const state = table.getSortState();
Sort not working: Check if sortable: false is set on column
Custom sort not applied: Ensure sortFunction returns -1, 0, or 1
Server sort errors: Verify serverSortLoader returns correct format
Performance issues: Consider server-side sorting for large datasets
// Check if sorting is enabled
console.log(table.sortingManager?.options);
// View current sort state
console.log(table.getSortState());
// Test sort function
const column = table.options.columns.find(c => c.name === 'salary');
console.log(column.sortFunction?.(100, 200)); // Should return -100
See the included examples for working demonstrations:
examples/sorting-test.html - Basic sorting functionalityexamples/sorting-demo.html - Comprehensive feature showcaseexamples/server-sorting.html - Server-side sorting exampleThe sorting feature is now ready for production use and provides a solid foundation for future enhancements like advanced filtering integration and custom sort controls.