TablixJS provides powerful column filtering capabilities with support for multiple filter types, custom operators, and both client-side and server-side filtering.
beforeFilter and afterFilterconst table = new Table('#myTable', {
data: myData,
columns: myColumns,
filtering: {
enabled: true,
mode: 'client', // 'client' or 'server'
showBadges: true,
showTooltips: true,
debounceDelay: 300
}
});
| Option | Type | Default | Description |
|---|---|---|---|
enabled |
boolean | true |
Enable/disable filtering |
mode |
string | 'client' |
Filtering mode: 'client' or 'server' |
serverFilterLoader |
function | null |
Function for server-side filtering |
debounceDelay |
number | 300 |
Debounce delay for input filters (ms) |
showBadges |
boolean | true |
Show filter count badges |
showTooltips |
boolean | true |
Show filter summary tooltips |
Filter icons (🞃) appear in column headers next to sort indicators. Clicking opens a dropdown with filtering options.
The dropdown provides two tabs:
applyFilter(columnName, filterConfig)Apply a filter to a specific column.
// Value filter
await table.applyFilter('status', {
type: 'value',
values: ['Active', 'Pending']
});
// Condition filter
await table.applyFilter('name', {
type: 'condition',
conditions: [
{ operator: 'beginsWith', value: 'A' },
{ operator: 'contains', value: 'son' }
]
});
clearFilter(columnName)Clear filter for a specific column.
await table.clearFilter('status');
clearAllFilters()Clear all active filters.
await table.clearAllFilters();
getActiveFilters()Get all active filters.
const filters = table.getActiveFilters();
// Returns: { columnName: filterConfig, ... }
getColumnFilter(columnName)Get filter state for a specific column.
const filter = table.getColumnFilter('status');
// Returns: { type, config, isActive } or null
Allows users to select/deselect specific values from the column.
{
type: 'value',
values: ['Active', 'Pending', 'Inactive']
}
Allows users to create conditions using operators.
{
type: 'condition',
conditions: [
{ operator: 'beginsWith', value: 'A' },
{ operator: 'contains', value: 'manager' }
]
}
| Operator | Label | Description | Requires Value |
|---|---|---|---|
none |
None | No filtering | No |
isEmpty |
Is empty | Field is empty/null | No |
isNotEmpty |
Is not empty | Field has value | No |
equals |
Is equal to | Exact match | Yes |
notEquals |
Is not equal to | Does not match | Yes |
beginsWith |
Begins with | Starts with value | Yes |
endsWith |
Ends with | Ends with value | Yes |
contains |
Contains | Contains value | Yes |
notContains |
Does not contain | Does not contain value | Yes |
Register custom operators for specialized filtering:
table.filterManager.registerOperator('isEven', {
label: 'Is even number',
apply: (value) => {
const num = parseInt(value);
return !isNaN(num) && num % 2 === 0;
}
});
// Use custom operator
await table.applyFilter('id', {
type: 'condition',
conditions: [{ operator: 'isEven' }]
});
{
label: 'Display label',
apply: (cellValue, filterValue) => boolean
}
For large datasets, implement server-side filtering:
const table = new Table('#myTable', {
filtering: {
enabled: true,
mode: 'server',
serverFilterLoader: async (params) => {
// params: { filters, sort, 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
};
}
}
});
The serverFilterLoader receives:
{
filters: {
columnName: { type: 'value'|'condition', ... }
},
sort: { column: 'name', direction: 'asc' },
page: 1,
pageSize: 10
}
Listen for filter events to respond to user actions:
table.eventManager.on('beforeFilter', (data) => {
console.log('About to filter:', data);
// data: { columnName, filterConfig, currentFilters }
});
table.eventManager.on('afterFilter', (data) => {
console.log('Filter applied:', data);
// data: { columnName, filterConfig, filteredData, activeFilters }
});
Filters work seamlessly with sorting:
await table.applyFilter('department', {
type: 'value',
values: ['Engineering']
});
await table.sort('name', 'asc'); // Sort filtered results
Pagination automatically resets to first page when filters change:
await table.applyFilter('status', {
type: 'value',
values: ['Active']
});
// Pagination automatically goes to page 1
Filtering uses CSS custom properties for theming:
:root {
--tablix-btn-active-color: #007bff;
--tablix-dropdown-bg: white;
--tablix-border-color: #dee2e6;
/* ... more variables */
}
/* Dark theme support */
[data-theme="dark"] {
--tablix-dropdown-bg: #343a40;
--tablix-border-color: #495057;
/* ... dark theme overrides */
}
const batchApplyFilters = async (filterConfigs) => {
for (const [columnName, config] of Object.entries(filterConfigs)) {
await table.applyFilter(columnName, config);
}
};
await batchApplyFilters({
status: { type: 'value', values: ['Active'] },
department: { type: 'value', values: ['Engineering'] },
salary: { type: 'condition', conditions: [{ operator: 'contains', value: '7' }] }
});
// Save current filter state
const currentFilters = table.getActiveFilters();
localStorage.setItem('tableFilters', JSON.stringify(currentFilters));
// Restore filter state
const savedFilters = JSON.parse(localStorage.getItem('tableFilters') || '{}');
for (const [columnName, config] of Object.entries(savedFilters)) {
await table.applyFilter(columnName, config);
}
// Access FilterUI for customization
const filterUI = table.filterUI;
// Extend with custom behaviors
filterUI.customMethod = function() {
// Custom logic
};
If upgrading from the basic filtering in DataManager:
// Old way (still supported)
await table.filter({ name: 'John' });
// New way (recommended)
await table.applyFilter('name', {
type: 'condition',
conditions: [{ operator: 'contains', value: 'John' }]
});
The legacy filter() method continues to work for backward compatibility.