A versatile, interactive feature designed to manage, and visualize large amounts of information in a table format.
The q2-data-table component is an incredibly powerful tool that generates an HTML table with the data that you provide. If you require extra control over specific cells, you can use a range of dynamically defined slots. These slots enable you to do things like:
Additionally, there are attributes and properties that allow you to alter the appearance and functionality of the table. For instance, you can:
Read on to discover all you can do!
The q2-data-table has two different properties that you are responsible for providing data to. One is headers , and the other is rows. Below are type definitions of both.
The data you provide to the headers property will be an array of objects with the following data structure.
interface Q2DataTableHeader {
title: string;
// Will be autogenerated from the title if not provided
// The key is used to grab the data from the row data
key?: string;
// 'auto' to use built-in sorting for this column
// 'manual' to implement your own sorting for this column
sortable?: 'auto' | 'manual';
// Indicates in what direction the data is sorted
sorted?: 'ASC' | 'DESC';
// Limits the number of rows that are displayed in a cell
// Content will be truncated if it exceeds the limit
lineClamp?: number;
// Defines alignment of the content within each cell in this column
// Defaults to 'center'
align?: 'start' | 'center' | 'end';
verticalAlign?: 'top' | 'bottom';
ariaLabel?: string;
// Defines the width of the column
width?: string;
// Defines the background of the column
backgroundColor?: string;
// Defines the content type for every cell in this column for styling puposes
type?: 'text' | 'number' | 'icon' | 'badge' | 'boolean' | 'code';
// When type = 'badge'
badgeStatus?: 'info' | 'alert' | 'warning' | 'success';
badgeTheme?: 'primary' | 'secondary' | 'tertiary';
}Similarly, the data you pass to rows is an array of objects with the following structure.
interface Q2DataTableRow {
id: string | number;
selected?: boolean;
expanded?: boolean;
disabled?: boolean;
cells: Record<string, string | number | Q2DataTableCell>
}
interface Q2DataTableCell {
value: string | number;
// Defines alignment of the content within this cell
// Takes priority over the column's `align` property when provided
// Defaults to 'center'
align?: 'start' | 'center' | 'end';
verticalAlign?: 'top' | 'bottom';
ariaLabel?: string;
// Defines the content type for this cell for styling purposes
// Takes priority over the column's `type` property when provided
type?: 'text' | 'number' | 'icon' | 'badge' | 'boolean' | 'code';
// Limits the number of rows that are displayed in a cell
// Content will be truncated if it exceeds the limit
lineClamp?: number;
// When type = 'badge'
badgeStatus?: 'info' | 'alert' | 'warning' | 'success';
badgeTheme?: 'primary' | 'secondary' | 'tertiary';
}The cells property is an object where each property key corresponds to a key defined for one of the headers.
With that said, let's look at a sample set of data that you can provide to a q2-data-table to be displayed.
const headerData = [
{
title: 'Day of Week',
key: 'day',
backgroundColor: 'var(--t-gray-14)',
},
{ title: 'Sales', key: 'sales', align: 'center' },
{ title: 'Revenue', key: 'revenue', align: 'center', sortable: true },
];
const rowData = [
{
id: 1,
cells: {
day: 'Monday',
sales: 93,
revenue: '$4,650',
},
},
{
id: 2,
cells: {
day: 'Tuesday',
sales: 127,
revenue: '$6,350',
},
},
{
id: 3,
cells: {
day: 'Wednesday',
sales: 121,
revenue: '$6,050',
},
},
{
id: 4,
cells: {
day: 'Thursday',
sales: 140,
revenue: '$7,000',
},
},
{
id: 5,
cells: {
day: 'Friday',
sales: 83,
revenue: '$4,150',
},
},
];From here, you need to provide the q2-data-table with this data:
const salesTable = document.querySelector('q2-data-table');
salesTable.headers = headerData;
salesTable.rows = rowData;While q2-data-table does a great job at displaying the data you need just by passing data into the component via properties, we understand that there will be times you want to customize the content. For this, we've exposed a series of dynamically named slots to allow you to do this.
In addition, by utilizing slots, you can further enhance your use of q2-data-table to provide expandable content or dropdowns to display a list of options for each row.
header-cell-<key>The <key> identifies the column from the key property in the headers data.
With this slot, you can override the content of any header cell in the table. Using the header cell data from the Data Structure section above as reference, we use a dropdown as the "Day of Week" header.
<q2-data-table>
<q2-dropdown slot="header-cell-day" label="Day of Week" type="icon" icon="options">
<q2-dropdown-item value="Home">Home</q2-dropdown-item>
<q2-dropdown-item value="Download as PDF">Download as PDF</q2-dropdown-item>
<q2-dropdown-item value="Discombobulate">Discombobulate</q2-dropdown-item>
</q2-dropdown>
</q2-data-table>row-<id>-cell-<key>The <id> corresponds to the id property provided for each entry in the rows property. Likewise, the <key> identifies the cell/column from the key property on each entry in the headers data.
With this slot, you can override the content of any cell in any row of the table. Using the data from the Data Structure section above as a reference, we can replace the "Sales" cell on the row for "Thursday" with our own custom content:
<q2-data-table>
<div slot="row-4-cell-sales">🤯 Lots</div>
</q2-data-table>row-<id>-dropdownThe <id> corresponds to the id property provided for each entry in the rows property.
One typical behavior is to have each row of a table contain a dropdown that presents actions to a user that they can take on that particular row of data. Due to the implementation of q2-dropdown and its intricacies, we are also exposing this as a slot. Again using the data from the Data Structure section, we can add a dropdown to the row for "Thursday" like this:
<q2-data-table>
<q2-dropdown
slot="row-4-dropdown"
icon="options"
alignment="right"
>
<q2-dropdown-item value="second">Report</q2-dropdown-item>
<q2-dropdown-item value="third">Ask question</q2-dropdown-item>
</q2-dropdown>
</q2-data-table>row-<id>-expandable-contentThe <id> corresponds to the id property provided for each entry in the rows property.
Another common desire is to have a table row be clickable, where upon clicking, it expands to reveal more detailed content. Because this often requires complex HTML and Javascript to display the desired results, we expose it as a slot that you can optionally utilize. The following example adds expandable content to the "Thursday" row:
But you already knew that.
<q2-data-table>
<div slot='row-4-expandable-content'>
<h3>Thursday Was Great</h3>
<p>But you already knew that.</p>
</div>
</q2-data-table>empty-tableWith this slot you can customize the look of your table's body when no row data is present. Alternatively, you may use the `emptyIcon` and `emptyMessage` properties to customize the empty state of the table with a `q2-icon` and custom text.
<q2-data-table>
<div slot="empty-table" style="display: flex; justify-content: center; align-items: center; gap: 10px;">
<q2-icon type="warning"></q2-icon>
<b>Table has no row data.</b>
</div>
</q2-data-table>By default, if a column has sortable: 'auto' set in the header data, the component will do its best to sort the data you provide in the rows property automatically. This works for most use cases you may have. However, a common use case is when you have multiple pages of content or need to provide a more detailed algorithm with which to sort your data.
For that, we recommend setting sortable: 'manual' in the desired header data, and listening to the sort event that is emitted from the component when you click on a sortable column header. Here is an example.
const dataTableElement = document.querySelector("q2-data-table")
function sortTransactions(event) {
// Calling preventDefault() will tell the Data Table
// NOT to perform the default sort functionality
event.preventDefault();
const {
direction,
header: { key },
} = event.detail;
dataTableElement.rows = [
...allTransactions.sort((a, b) => {
if (direction === 'ASC') return a.cells[key] > b.cells[key] ? 1 : -1;
else return a.cells[key] < b.cells[key] ? 1 : -1;
}),
]);
// You'll also want to update the headers to reflect which
// column was sorted and it's direction
dataTableElement.headers = allHeaders.map(header => (
{ ...header, sorted: header.key === key ? direction : undefined }))
);
}
tableElement.current?.addEventListener('sort', sortTransactions);The q2-data-table element has multiple slots that can be used to insert custom content into the component.
An optional slot to display custom content when the table is empty.
A slot for the content of any cell in the header of the table.
A slot for overriding the content of any cell in any row of the table with custom content.
A slot to provide a Dropdown for a row.
A slot that makes the row expandable and displays the provided content.
The q2-data-table element has one or more properties that support text localization. Those properties are indicated by the localizable badge in the description.
borderedAdds borders between rows and/or columns in the table.
captionProvides a caption for the data table.
clickableAdds the ability to click a row and have the table emit an event with the selected row's data.
densityDetermines the amount of padding for each of the cells in the table.
emptyIconempty-iconDetermines the q2-icon that will display when rows has no value.
emptyMessageempty-messageDetermines the message that will display when rows has no value.
headersDefines the headers of the table.
Example:
element.headers = [
{
title: 'Day of the Week',
key: 'day',
},
{
title: 'Sales',
key: 'sales',
align: 'end',
}
]hideCaptionhide-captionHides the caption from view, but still makes it available to screen readers for accessibility purposes.
hideClickablehide-clickableVisually hides the Select button that displays when clickable=true. It will still be discoverable by assistive technologies.
Use of this property requires clickable to be set to true.
loadingDisplays a loading state on the table to indicate background activity.
rowsDefines the rows of the table.
Example:
element.rows = [
{
id: 1,
cells: {
day: 'Monday',
sales: 93
}
},
{
id: 2,
cells: {
day: 'Tuesday',
sales: 127
}
},
{
id: 3,
cells: {
day: 'Wednesday',
sales: 121
}
]selectModeselect-modeDetermines if the selectable checkboxes allow for multi-select or not. If set to "single", once a row is selected, all other rows will be disabled.
See the documentation on the select event for how to handle selections.
Use of this property requires selectable to be set to true.
selectableAdds a checkbox to each row of the table making it selectable.
shadowedAdds a shadow to the table
stripedEnables alternating background colors for the table rows
The q2-data-table element exposes events that can be used to send and receive data from the component based on user interaction.
Emitted when a row is clicked.
Requires the clickable prop to be set to true.
Call event.preventDefault() to prevent the default click behavior.
{ row: Q2DataTableSerializedRow; }Emitted when a row is selected.
Requires the selectable prop to be set to true.
Call event.preventDefault() to prevent the default selection behavior.
{ row: Q2DataTableSerializedRow; rows: Q2DataTableSerializedRow[]; allSelected: boolean; }Emitted when the select-all checkbox is toggled.
Requires the selectable prop to be set to true and the selectMode prop to be set to multiple.
Call event.preventDefault() to prevent the default behavior.
{ checked: boolean; }Emitted when a column is sorted.
Requires the sortable prop to be set to true on the column.
Call event.preventDefault() to prevent the default sorting behavior.
{ header: Q2DataTableHeader; direction: "ASC" | "DESC"; }Emitted when an expandable row is toggled.
Requires content in the row-{id}-expandable-content slot.
Call event.preventDefault() to prevent the default toggling behavior.
{ row: Q2DataTableSerializedRow; }The q2-data-table element exposes methods that can be used to perform various actions on the component.
A method to click a row that accepts a row ID that is will be clicked.
clickRow(rowId: number | string) => Promise<void>A method that returns the plain text value of a particular cell (including slot content).
getCellContent(rowId: number | string, columnKey: string) => Promise<string>A method to sort a column that accepts a header object with key and sorted property.
sortColumn(header: Q2DataTableHeader) => Promise<void>A method to toggle row expansion that accepts a row ID that will be clicked to expand or collapse the expandable content
toggleRowExpansion(rowId: number | string) => Promise<void>A method to toggle row selection that accepts a row ID whose checkbox will be checked, if the feature is enabled.
toggleRowSelect(rowId: number | string) => Promise<void>A method to toggle select all button (checkbox) on left top corner.
toggleSelectAllRows() => Promise<void>Initial Release
Add boolean cell type
Support for clickable rows, line-clamping cell content, and a code cell type
Support for disabling the checkbox of a specific row
Support for a default empty state with optional slot for override
Support for custom header cells
Additional ways to customize borders
Support custom sorting algorithms for columns
The following CSS variables are available to override the default theme styles of the q2-data-tablecomponent.
Many Tecton components consume other components to maintain visual and functional consistency. If you are looking for a CSS variable you think should exist but are not seeing it, it may be defined in one of the dependent components below. Either way, if you think it's something we should expose more conveniently, let us know!