The TablixJS Column Formatting System provides a flexible, lightweight, and fully optional way to format cell values using the modern Intl APIs. This system is inspired by Handsontable cell formats but designed to be more flexible and lightweight.
import Table from './src/core/Table.js';
const table = new Table('#container', {
data: [
{ name: 'Alice', salary: 95000, joinDate: '2022-03-15', bonus: 0.15 }
],
columns: [
{ name: 'name', title: 'Employee' }, // Raw value
{ name: 'salary', title: 'Salary', format: 'currency', currency: 'USD' },
{ name: 'joinDate', title: 'Join Date', format: 'date' },
{ name: 'bonus', title: 'Bonus', format: 'percent' }
]
});
{
name: 'columnName', // Required: data property name
title: 'Display Name', // Optional: header display text
format: 'formatType', // Optional: format type
locale: 'en-US', // Optional: locale for formatting
formatOptions: { ... }, // Optional: Intl API options
currency: 'USD', // Required for currency format
renderer: (value, row, formattedValue) => { ... } // Optional: custom renderer
}
Basic string conversion with null/undefined handling.
{ name: 'description', title: 'Description', format: 'text' }
Uses Intl.NumberFormat for numeric values.
// Basic number
{ name: 'rating', format: 'number' }
// With decimal places
{
name: 'score',
format: 'number',
formatOptions: {
minimumFractionDigits: 2,
maximumFractionDigits: 2
}
}
// With locale
{
name: 'population',
format: 'number',
locale: 'de-DE',
formatOptions: { useGrouping: true }
}
Uses Intl.NumberFormat with currency style.
// Basic USD currency
{
name: 'salary',
format: 'currency',
currency: 'USD'
}
// EUR with German locale
{
name: 'price',
format: 'currency',
currency: 'EUR',
locale: 'de-DE'
}
// Custom options
{
name: 'budget',
format: 'currency',
currency: 'GBP',
locale: 'en-GB',
formatOptions: {
minimumFractionDigits: 0,
maximumFractionDigits: 0
}
}
Uses Intl.DateTimeFormat for date/time values.
// Basic date
{ name: 'joinDate', format: 'date' }
// Short date style
{
name: 'createdAt',
format: 'date',
formatOptions: { dateStyle: 'short' }
}
// Custom format
{
name: 'updatedAt',
format: 'date',
locale: 'fr-FR',
formatOptions: {
year: 'numeric',
month: 'long',
day: '2-digit',
weekday: 'long'
}
}
// Date and time
{
name: 'timestamp',
format: 'date',
formatOptions: {
dateStyle: 'short',
timeStyle: 'medium'
}
}
Uses Intl.NumberFormat with percent style.
// Basic percentage (0.15 → 15%)
{ name: 'bonus', format: 'percent' }
// With decimals
{
name: 'commission',
format: 'percent',
formatOptions: { minimumFractionDigits: 2 }
}
// With locale
{
name: 'growth',
format: 'percent',
locale: 'de-DE',
formatOptions: { signDisplay: 'always' }
}
Custom renderers have priority over formatting but can use formatted values.
renderer: (value, row, formattedValue) => {
// value: raw cell value
// row: complete row object
// formattedValue: formatted value (if format is specified)
return 'HTML string or text';
}
{
name: 'salary',
format: 'currency',
currency: 'USD',
renderer: (value, row, formattedValue) => {
const color = value >= 80000 ? 'green' : 'red';
return `<span style="color: ${color}">${formattedValue}</span>`;
}
}
{
name: 'status',
renderer: (value) => {
return value ? 'Active' : 'Inactive';
}
}
{
name: 'fullName',
renderer: (value, row) => {
return `${row.firstName} ${row.lastName}`;
}
}
'en-US', 'de-DE', 'fr-FR', 'ja-JP', 'ar-SA'All formatOptions are passed directly to the respective Intl API:
formatOptions: {
dateStyle: 'full' | 'long' | 'medium' | 'short',
timeStyle: 'full' | 'long' | 'medium' | 'short',
year: 'numeric' | '2-digit',
month: 'numeric' | '2-digit' | 'long' | 'short' | 'narrow',
day: 'numeric' | '2-digit',
weekday: 'long' | 'short' | 'narrow',
hour: 'numeric' | '2-digit',
minute: 'numeric' | '2-digit',
second: 'numeric' | '2-digit',
timeZone: 'UTC' | 'America/New_York' | ...
}
formatOptions: {
minimumFractionDigits: 0,
maximumFractionDigits: 3,
minimumSignificantDigits: 1,
maximumSignificantDigits: 21,
useGrouping: true,
signDisplay: 'auto' | 'never' | 'always' | 'exceptZero'
}
format specifiedcurrency for simple numbersThe formatting system gracefully handles various error conditions:
// These won't break the table:
{ date: 'invalid-date', number: 'not-a-number', currency: null }
// Warns and falls back to raw value:
{ name: 'field', format: 'unsupported-format' }
// Currency without currency code:
{ name: 'price', format: 'currency' } // Will show warning
The system is designed for future extension:
// Future API for custom formats:
table.columnManager.registerFormat('filesize', (column) => {
return (value) => {
// Custom formatting logic
return formatFileSize(value);
};
});
// Usage:
{ name: 'fileSize', format: 'filesize' }
The modular design allows for future plugins that could add:
const employeeTable = new Table('#employees', {
data: employees,
columns: [
{ name: 'id', title: 'ID' },
{ name: 'name', title: 'Employee Name' },
{ name: 'department', title: 'Department' },
{
name: 'salary',
title: 'Annual Salary',
format: 'currency',
currency: 'USD',
formatOptions: { minimumFractionDigits: 0 }
},
{
name: 'bonus',
title: 'Bonus Rate',
format: 'percent',
formatOptions: { minimumFractionDigits: 1 }
},
{
name: 'joinDate',
title: 'Hire Date',
format: 'date',
formatOptions: {
year: 'numeric',
month: 'short',
day: '2-digit'
}
},
{
name: 'rating',
title: 'Performance',
format: 'number',
formatOptions: { minimumFractionDigits: 1, maximumFractionDigits: 1 }
}
]
});
const financialTable = new Table('#financial', {
data: transactions,
columns: [
{ name: 'date', title: 'Date', format: 'date', formatOptions: { dateStyle: 'short' } },
{ name: 'description', title: 'Description' },
{
name: 'amount',
title: 'Amount',
format: 'currency',
currency: 'EUR',
locale: 'de-DE',
renderer: (value, row, formattedValue) => {
const color = value >= 0 ? 'green' : 'red';
return `<span style="color: ${color}">${formattedValue}</span>`;
}
},
{
name: 'tax',
title: 'Tax Rate',
format: 'percent',
locale: 'de-DE'
}
]
});
Test your formatting with various data types:
const testData = [
{ value: 123.456, date: '2023-12-25', currency: 50000 },
{ value: null, date: null, currency: null },
{ value: 'invalid', date: 'invalid-date', currency: 'not-number' },
{ value: 0, date: new Date(), currency: 0 }
];
initializeColumns(columns)Initialize columns and compile formatters.
formatCellValue(columnName, value, row)Format a cell value for display.
getColumn(columnName)Get column definition by name.
getColumns()Get all column definitions.
getSupportedFormats()Get array of supported format types.
See the Intl documentation for complete options:
This formatting system integrates seamlessly with TablixJS's existing features including sorting, pagination, and event hooks.