Table View
Component for displaying data in table format.
NOTE
KTableView does not handle data management capabilities like data fetching, functional pagination, sorting or searching. If you are looking for a component that integrates with the data layer, check out KTable.
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
Props
headers
Array of objects that represent table columns along with some configurations that should apply to each of the columns (whether a column is sortable, hidable, etc).
interface TableViewHeader {
/** must be unique for each column, see Reserved Header Keys section for more information about 'actions' key value */
key: string
/** visible column header text */
label: string
/** in a nutshell, this property defines whether sort icon should be displayed next to the column header and whether the column header will emit sort event upon clicking on it */
sortable?: boolean
/** allow toggling column visibility */
hidable?: boolean
/** when provided, an info icon will be rendered next to the column label, upon hovering on which the tooltip will be revealed */
tooltip?: string
/** whether column header text should be hidden (only visible to screen readers) */
hideLabel?: boolean
}
NOTE
If at least one column is hidable
in the table, KTableView will render a dropdown on the right of the table toolbar directly above the table, which will provide an interface for showing/hiding columns to the user.
For an example of headers
prop usage please refer to data
prop documentation below.
Reserved Header Keys
actions
- the column displays an actions KDropdown button for each row and displays no label (as ifhideLabel
wastrue
; you can sethideLabel
parameter tofalse
to show the label). KTableView will automatically render the actions dropdown button with an icon and you simply need to provide dropdown items via theaction-items
slot.
data
Data to be rendered in the table. Accepted interface is an array of objects where each property key should have a corresponding key
in the headers
prop.
type TableViewData = Record<string, any>[]
Full Name | Username | Email | Row actions |
---|---|---|---|
Leanne Graham | Bret | Sincere@april.biz | |
Ervin Howell | Antonette | Shanna@melissa.tv | |
Clementine Bauch | Samantha | Nathan@yesenia.net | |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org | |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca | |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info | |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz | |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me | |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io | |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<template>
<KTableView
:data="tableData"
:headers="headers"
@sort="sortData"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #action-items>
<KDropdownItem>
Edit
</KDropdownItem>
<KDropdownItem
danger
has-divider
>
Delete
</KDropdownItem>
</template>
</KTableView>
</template>
<script setup lang="ts">
import type { TableViewHeader, TableViewData } from '@kong/kongponents'
const headers: Array<TableViewHeader> = [
{
key: 'name',
label: 'Full Name',
},
{
key: 'username',
label: 'Username',
sortable: true,
tooltip: 'Unique for each user.',
},
{
key: 'email',
label: 'Email',
hidable: true,
},
{
key: 'actions',
label: 'Row actions',
},
]
const tableData = ref<TableViewData>([
{
id: 1,
// notice that property keys in data object correspond to each respective key in headers const
name: 'Leanne Graham',
username: 'Bret',
email: 'Sincere@april.biz'
},
{
id: 2,
name: 'Ervin Howell',
username: 'Antonette',
email: 'Shanna@melissa.tv'
},
...
])
const sortData = (sortData: TableSortPayload): void => {
const data = [...tableData.value]
const { sortColumnKey, sortColumnOrder } = sortData || { sortColumnKey: 'username', sortColumnOrder: 'asc' }
data.sort((a: Record<string, any>, b: Record<string, any>) => {
if (sortColumnKey === 'username') {
if (sortColumnOrder === 'asc') {
if (a.username > b.username) {
return 1
} else if (a.username < b.username) {
return -1
}
return 0
} else {
if (a.username > b.username) {
return -1
} else if (a.username < b.username) {
return 1
}
return 0
}
}
return 0
})
tableData.value = data
}
</script>
NOTE
Notice that in the example above the Username column is sortable
and the Email column is hidable
.
loading
Boolean to control whether the component should display the loading state. Defaults to false
.
<KTableView
loading
:data="tableData"
:headers="headers"
/>
error
Boolean to control whether the component should display the error state. Defaults to false
. See error state section for more customization options.
<KTableView
error
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
resizeColumns
Allow table column width to be resizable (defaults to false
). Adjusting a column's width will trigger an update:table-preferences
event.
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
resize-columns
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
rowHover
Boolean to control whether table should display hover state upon hovering rows. Defaults to true
.
tablePreferences
Can be used to pass object with locally stored preferences for different table configuration options. For example, when user resizes a column in a given table, update:table-preferences
event will be emitted - you can then save the value and re-apply it next time user encounters this table.
interface TablePreferences {
/** the number of items to display per page */
pageSize?: number
/** the column to sort by's `key` defined in the table headers */
sortColumnKey?: string
/** the order by which to sort the column, one of `asc` or `desc` */
sortColumnOrder?: SortColumnOrder
/** the customized column widths, if resizing is allowed */
columnWidths?: Record<string, number>
/** column visibility, if visibility is toggleable */
columnVisibility?: Record<string, boolean>
}
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:table-preferences="{ columnVisibility: { email: false } }"
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
rowAttrs
Function for adding custom attributes to each row. The function should return an object with key: value
pairs for each attribute.
The passed function receives row value object as an argument.
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:row-attrs="(row) => { return { 'data-testid': `row-${row.id}` } }"
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
rowLink
Function for turning row into a link. The function receives row value object as an argument and should return an object with two optional parameters:
interface RowLink {
/** RouteLocationRaw or url string for row link */
to?: RouteLocationRaw | string
/** Target for row link */
target?: '_self' | '_blank' | '_parent' | '_top'
}
<template>
<KTableView
:row-link="getRowLink"
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
</template>
<script setup lang="ts">
import type { RowLink } from '@kong/kongponents'
const headers = [...]
const tableData = [...]
const getRowLink = (row: Record<string, any>): RowLink => ({
// using static route for demonstration purposes
// but you can generate dynamic routes based on the row data
to: { name: 'home' }, // pass a string to render the link as an anchor element instead of a router-link
target: '_blank',
})
</script>
cellAttrs
Function for adding custom attributes to each table cell. The function should return an object with key: value
pairs for each attribute.
The passed function receives an object with these parameters as an argument:
{
headerKey: string // header key
row: object // row value
rowIndex: number // row index
colIndex: index // column index
}
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:cell-attrs="({ headerKey, row }) => { return { 'data-testid': `column-${headerKey}-row-${row.id}` } }"
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
maxHeight
Limit the table height by passing a number, in pixels. If the table height exceeds the specified number, it will be scrollable. Table header is a position: sticky;
element and will always be visible.
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
max-height="300"
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
paginationAttributes
Object to be passed to underlying pagination component. See KPagination props for more details. Expects an object of type TablePaginationAttributes
:
interface TablePaginationAttributes {
totalCount?: number
pageSizes?: number[]
initialPageSize?: number
currentPage?: number
offset?: boolean
disablePageJump?: boolean
offsetPreviousButtonDisabled?: boolean
offsetNextButtonDisabled?: boolean
}
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
<KTableView
:pagination-attributes="{ totalCount: tableData.length, pageSizes: [5, 10] }"
:data="paginatedData"
:headers="headers"
/>
hidePagination
A boolean to hide pagination element (defaults to false
).
States
Empty
<KTableView
:data="[]"
:headers="headers"
/>
Set the following props to handle empty state:
emptyStateTitle
- Title text for empty stateemptyStateMessage
- Message for empty stateemptyStateIconVariant
- Icon variant for empty state (see KEmptyState component props)emptyStateActionMessage
- Button text for empty state actionemptyStateActionRoute
- Route for empty state actionemptyStateButtonAppearance
- Appearance of empty state action button. See KButtonappearance
prop for details
TIP
To display an icon inside of action button, you can use the empty-state-action-icon
slot.
When the empty state action button is clicked, KTableView emits the empty-state-action-click
event.
<KTableView
:data="[]"
:headers="headers"
empty-state-title="No Workspaces exist"
empty-state-message="Adding a new Workspace will populate this table."
empty-state-icon-variant="kong"
empty-state-action-message="Create a Workspace"
empty-state-action-route="/"
empty-state-button-appearance="secondary"
>
<template #empty-state-action-icon>
<AddIcon />
</template>
</KTableView>
Error
Set the error
prop to true
to enable the error state.
<KTableView
error
:data="tableData"
:headers="headers"
/>
Set the following properties to customize the error state:
errorStateTitle
- Title text for the error stateerrorStateMessage
- Message for the error stateerrorStateActionMessage
- Button text for the error state actionerrorStateActionRoute
- Route for the error state action
A error-action-click
event is emitted when error state action button is clicked.
<KTableView
error
:data="tableData"
:headers="headers"
error-state-title="Something went wrong"
error-state-message="Error loading data."
error-state-action-message="Report an Issue"
error-state-action-route="/"
/>
Slots
Column Header
You can slot in your custom content into each column header. For that, use column key
value prefixed with column-*
like in the example below.
Slot props:
column
- column header object
Full Name | Username | Email Beta |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #column-email="{ column }">
{{ column.label }} <KBadge>Beta</KBadge>
</template>
</KTableView>
Cell
You can provide each individual cell's content via slot. Each cell slot is named after the header key
it corresponds to.
Slot props:
row
- table row objectrowKey
- table row indexrowValue
- the cell value
NOTE
This slot is not supported for the actions
column.
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #email="{ rowValue }">
<KCopy :text="rowValue" />
</template>
</KTableView>
Header Tooltip
Utilize HTML in the column header's tooltip by utilizing this slot. Similar to the column header slot, it uses the column key
value prefixed with tooltip-*
as shown in the example below.
Slot props:
column
- column header object
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #tooltip-email>
HubSpot Id: <code>8576925e-d7e0-4ecd-8f14-15db1765e69a</code>
</template>
</KTableView>
toolbar
The toolbar is rendered directly above the table and is useful for providing table controls like search or filter fields.
Full Name | Username | Email |
---|---|---|
Leanne Graham | Bret | Sincere@april.biz |
Ervin Howell | Antonette | Shanna@melissa.tv |
Clementine Bauch | Samantha | Nathan@yesenia.net |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #toolbar>
<KInput placeholder="Search">
<template #before>
<SearchIcon />
</template>
</KInput>
<KButton size="large">
<AddIcon /> Add user
</KButton>
</template>
</KTableView>
empty-state
Slot content to be displayed when empty.
empty-state-action-icon
Slot for icon to be displayed in front of action button text in empty state. See empty state section for example of usage of this slot.
error-state
Slot content to be displayed when in error state.
action-items
Slot for passing action dropdown items. See KDropdownItem component docs for details.
Slot props:
row
- table row objectrowKey
- table row index
NOTE
This slot is only available when the actions
header key is present in headers
.
Full Name | Username | Email | Row actions |
---|---|---|---|
Leanne Graham | Bret | Sincere@april.biz | |
Ervin Howell | Antonette | Shanna@melissa.tv | |
Clementine Bauch | Samantha | Nathan@yesenia.net | |
Patricia Lebsack | Karianne | Julianne.OConner@kory.org | |
Chelsey Dietrich | Kamren | Lucio_Hettinger@annie.ca | |
Mrs. Dennis Schulist | Leopoldo_Corkery | Karley_Dach@jasper.info | |
Kurtis Weissnat | Elwyn.Skiles | Telly.Hoeger@billy.biz | |
Nicholas Runolfsdottir V | Maxime_Nienow | Sherwood@rosamond.me | |
Glenna Reichert | Delphine | Chaim_McDermott@dana.io | |
Clementina DuBuque | Moriah.Stanton | Rey.Padberg@karina.biz |
<KTableView
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #action-items>
<KDropdownItem>
Edit
</KDropdownItem>
<KDropdownItem
danger
has-divider
>
Delete
</KDropdownItem>
</template>
</KTableView>
Events
Row Events
@row:{event}
- returns the Event
, the row item, and the type. row-click
event is emitted whenever a row is clicked and the row click event handler is emitted, returns the row data
.
To avoid firing row clicks by accident, the row click handler ignores events coming from a
, button
, label
, input
, and select
elements (unless they have the disabled
attribute). As such click handlers attached to these element types do not require stopping propagation via @click.stop
.
The table in the example below contains buttons, inputs and links to demonstrate how KTableView handles clicks on different interactive elements within the table as well as clicks on its rows.
Try clicking below on the table row, and then within elements inside the table cells.
Column 1 | Column 2 | Column 3 |
---|---|---|
<KTableView
:data="tableData"
:headers="headers"
@row:click="onRowClick"
hide-pagination
/>
Cell Events
@cell:{event}
- returns the Event
, the cell value, and the type. cell-click
event is emitted whenever a cell is clicked and the cell click event handler is emitted, returns the cell data
.
The table in the example below contains buttons, inputs and links to demonstrate how KTableView handles clicks on different interactive elements within the table as well as clicks on its cells.
Column 1 | Column 2 | Column 3 |
---|---|---|
<KTableView
:data="tableData"
:headers="headers"
@cell:click="onCellClick"
hide-pagination
/>
Pagination Events
KTableView propagates all events emitted by underlying pagination component. See KPagination docs for more details.
sort
Emitted when user clicks on a sortable column heading. Event payload is object of type TableSortPayload
:
interface TableSortPayload {
prevKey: string
sortColumnKey: string
sortColumnOrder: string
}
Refer to data
prop usage for example.
empty-state-action-click
Emitted when empty state action button is clocked.
error-action-click
Emitted when error state action button is clicked.
update:table-preferences
Emitted when the user performs sorting, resizes columns or toggles column visibility. Event payload is object of type TablePreferences
interface (see tablePreferences
prop for details).