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 KTableData.
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
/** 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
}
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 |
<template>
<KTableView
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
/>
</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',
tooltip: 'Unique for each user.',
},
{
key: 'email',
label: 'Email',
hidable: true,
},
]
const tableData = ref<TableViewData>([...])
</script>
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.
Reserved Header Keys
Some header key values are treated specially.
bulkActions
The column displays individual checkboxes to allow selecting individual rows, while the column header displays a checkbox will check or uncheck all visible table rows. KTableView will render a dropdown on the right of the table toolbar directly above the table and you simply need to provide dropdown items via the bulk-action-items
slot.
IMPORTANT
Bulk actions column won't be rendered in case if:
- neither
bulk-action-items
, norbulk-actions
slots are provided rowKey
prop prop is not provided
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 |
<template>
<KTableView
:data="tableData"
:headers="headers"
row-key="id"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #bulk-action-items="{ selectedRows }">
<KDropdownItem danger>
Delete ({{ selectedRows.length }} items)
</KDropdownItem>
</template>
</KTableView>
</template>
<script setup lang="ts">
import type { TableViewHeader, TableViewData } from '@kong/kongponents'
const headers: Array<TableViewHeader> = [
{
key: 'bulkActions',
label: 'Bulk actions',
},
...
]
const tableData = ref<TableViewData>([ ... ])
</script>
actions
The column displays an actions KDropdown button for each row and displays no label (as if hideLabel
was true
; you can set hideLabel
parameter to false
to show the label). KTableView will automatically render the actions dropdown and you simply need to provide dropdown items via the action-items
slot.
NOTE
KTableView automatically displays the bulk action checkbox as the first column, and the actions
menu in the last column, when enabled.
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"
: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: 'actions',
label: 'Row actions',
},
...
]
const tableData = ref<TableViewData>([...])
</script>
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>
rowKey
Certain features of KTableView require a unique identifier to utilize for each row of table data.
The rowKey
prop provides a way to define which property of the row
object should serve as this unique identifier, or to generate a custom unique identifier for each row.
The rowKey
prop accepts either a unique string or a function that returns a unique string: string | ((row: Record<string, any>) => string)
.
If a string is provided which corresponds to a property of the row
, the unique identifier will utilize the row[rowKey]
as the unique identifier.
<template>
<KTableView
row-key="id"
:data="tableData"
:headers="headers"
/>
</template>
<script setup lang="ts">
import type { TableViewData } from '@kong/kongponents'
const tableData: TableViewData = [
{
id: 'a70642b3-20f2-4658-b459-fe1cbcf9e315',
...
},
{
id: '58c599a9-f453-41f3-9e64-0a7fc6caedad',
...
}
]
</script>
Alternatively, if a function is passed, it allows for the creation of a custom identifier based on the row data passed to the function.
<KTableView
:row-key="({ id, username }: Record<string, any>) => username + id"
:data="tableData"
:headers="headers"
/>
IMPORTANT
The value provided through the rowKey
prop must be unique for each row
of data, even for paginated data.
rowBulkActionEnabled
Function for enabling or disabling row selection when bulkActions
are enabled for the table. Helpful for making some rows unavailable for bulk actions selection. The function receives the row data object as a parameter and must return a boolean
or an object that matches the following interface:
type RowBulkAction = boolean | { enabled: boolean, disabledTooltip?: string }
When the function returns a boolean value of true
, bulk action selection will be enabled for the row.
When false
is returned, the bulk action checkbox will be disabled.
If an object is returned, the enabled
property determines if the row can be selected. The disabledTooltip
value, if provided, will show the string as a tooltip message if the user hovers over the disabled checkbox.
Default value is () => true
.
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 |
<template>
<KTableView
:row-bulk-action-enabled="getRowBulkActionEnabled"
row-key="id"
:data="tableData"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #bulk-action-items="{ selectedRows }">
<KDropdownItem danger>
Delete ({{ selectedRows.length }} items)
</KDropdownItem>
</template>
</KTableView>
</template>
<script setup lang="ts">
import type { RowBulkAction } from '@kong/kongponents'
...
const getRowBulkActionEnabled = (row: Record<string, any>): RowBulkAction => {
if (row.id === 2) {
return false
}
if (row.id === 3) {
return { enabled: false }
}
if (row.id === 4) {
return {
enabled: false,
disabledTooltip: 'This row is disabled.',
}
}
return true
}
</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
).
hidePaginationWhenOptional
Set this to true
to hide pagination when the table record count is less than or equal to the page size. Defaults to false
.
rowExpandable
Function for making a row expandable. The function receives row value object as an argument and should return a boolean value. Default value is () => false
.
Expandable rows controls | Full Name | Username | Type |
---|---|---|---|
Leanne Graham | Bret | Internal | |
Ervin Howell | Antonette | External | |
Clementine Bauch | Samantha | Internal | |
Patricia Lebsack | Karianne | External | |
Chelsey Dietrich | Kamren | Internal | |
Mrs. Dennis Schulist | Leopoldo_Corkery | External | |
Kurtis Weissnat | Elwyn.Skiles | Internal | |
Nicholas Runolfsdottir V | Maxime_Nienow | External | |
Glenna Reichert | Delphine | Internal | |
Clementina DuBuque | Moriah.Stanton | External |
<KTableView
:data="tableData"
:row-expandable="(row) => row.type.toLowerCase() === 'external'"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #row-expanded>
Lorem ipsum odor amet...
</template>
</KTableView>
rowExpanded
Use this prop to specify the initial expanded / collapsed state for each data row. The function receives the row value object as an argument and should return a boolean value. Default value is () => false
. When returned value is true
, a row is rendered expanded.
Expandable rows controls | Full Name | Username | Type |
---|---|---|---|
Leanne Graham | Bret | Internal | |
Ervin Howell | Antonette | External | |
Clementine Bauch | Samantha | Internal | |
Patricia Lebsack | Karianne | External | |
Chelsey Dietrich | Kamren | Internal | |
Mrs. Dennis Schulist | Leopoldo_Corkery | External | |
Kurtis Weissnat | Elwyn.Skiles | Internal | |
Nicholas Runolfsdottir V | Maxime_Nienow | External | |
Glenna Reichert | Delphine | Internal | |
Clementina DuBuque | Moriah.Stanton | External |
<KTableView
:data="tableData"
:row-expanded="(row) => row.id === tableData.find((dataRow) => dataRow.type.toLowerCase() === 'external')?.id"
:row-expandable="(row) => row.type.toLowerCase() === 'external'"
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #row-expanded>
Lorem ipsum odor amet...
</template>
</KTableView>
hideHeaders
A boolean to hide table headers. Only recomended when used in nested table. Refer to Expandable Rows section documentation for more details. Defaults to false
.
nested
A boolean to disable some of the table features like column visibility, column resizing, bulk actions and hide toolbar element in nested tables. Refer to Expandable Rows section documentation for more details. Defaults to false
.
hideToolbar
Prop for hiding toolbar. Useful when elements provided in the toolbar are not actionable (for example, when toolbar contains filter controls, however the fetcher returns no results as there are no records to filter by).
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="/"
/>
Expandable Rows
Data presented in a table often requires futher clarification or specification. The rowExpandable
prop allows some rows to be toggled, revealing or hiding additional information without the need to navigate away from the current view. Any content can be passed using the row-expanded
slot. However, when displaying a nested table in expanded rows, there are a few important considerations to be aware of.
Nested Table With Different Columns
A nested table represents data that differs from the parent table but is loosely related. This type of nested table does not require any special handling other than setting the nested
prop to true
.
Notice that column visibility, column resizing and bulk actions features, as well as toolbar
slot, are disabled in nested tables.
Expandable rows controls | Team Name | Manager | Slack Channel |
---|---|---|---|
Design | Leanne Graham | #team-design | |
Engineering | Ervin Howell | #team-engineering | |
Data | Clementine Bauch | #team-data | |
Support | Patricia Lebsack | #team-support |
<KTableView
:headers="parentHeaders"
:data="parentData"
:row-expandable="() => true"
resize-columns
:pagination-attributes="{ totalCount: parentData.length }"
>
<template #row-expanded>
<KTableView
:headers="nestedHeaders"
:data="nestedData"
nested
:pagination-attributes="{ totalCount: nestedData.length }"
/>
</template>
</KTableView>
NOTE
Both parent and nested tables in this example contain static data for demonstration purposes.
Nested Table With Same Columns
A nested table that complements the parent table requires some special handling:
- The
nested
prop must be set totrue
- Table headers can be hidden using the
hideHeaders
prop. Value still need to be passed through theheaders
prop, and this is where thenestedHeaders
slot prop becomes useful. It returns an array of header objects, simplifying the synchronization of column visibility when it is enabled in the parent table - To better align the columns of the parent and nested tables, the
columnWidths
slot prop can be utilized. It returns an object that can be passed to the nested table through thetablePreferences
prop. Each time a column is resized in the parent table, the nested table will be updated accordingly
NOTE
If bulk actions is enabled in parent table, it will be disabled in the nested table.
Expandable rows controls | Control Plane | Type | Nodes | Row actions |
---|---|---|---|---|
Group 1 | Control Plane Group | 3 | ||
Group 2 | Control Plane Group | 3 | ||
Group 3 | Control Plane Group | 3 | ||
Cloud 1 | Cloud Gateway | 2 | ||
Group 4 | Control Plane Group | 3 |
<KTableView
:headers="parentHeaders"
:data="parentData"
:row-expandable="(row) => row.type === 'Control Plane Group'"
resize-columns
:pagination-attributes="{ totalCount: parentData.length }"
>
<template #row-expanded="{ nestedHeaders, columnWidths }">
<KTableView
:headers="nestedHeaders"
:data="nestedData"
hide-headers
nested
:pagination-attributes="{ totalCount: nestedData.length }"
:table-preferences="{ columnWidths }"
/>
</template>
</KTableView>
NOTE
Both parent and nested tables in this example contain static data for demonstration purposes.
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>
NOTE
If toolbar
slot is not empty, the column visibility and/or bulk actions (whichever is enabled) dropdowns in the toolbar will be disabled when not actionable. If it is empty, the column visibility and/or bulk actions dropdowns will be hidden when not actionable.
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 object
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>
bulk-action-items
Slot for passing bulk action dropdown items.
Slot props:
selectedRows
- array of selected table row objects
See also: row-select
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 |
<template>
<KTableView
:data="paginatedData"
:headers="headers"
row-key="id"
:pagination-attributes="{ totalCount: tableData.length, pageSizes: [5, 10] }"
>
<template #bulk-action-items="{ selectedRows }">
<KDropdownItem danger>
Delete ({{ selectedRows.length }} items)
</KDropdownItem>
</template>
</KTableView>
</template>
<script setup lang="ts">
import type { TableViewHeader, TableViewData } from '@kong/kongponents'
const headers: Array<TableViewHeader> = [
{
key: 'bulkActions',
label: 'Bulk actions',
},
...
]
const tableData = ref<TableViewData>([ ... ])
const paginatedData = tableData.slice(...)
</script>
bulk-actions
Slot for passing custom bulk actions trigger element. Content provided through this slot will replace default bulk actions dropdown.
Slot props:
selectedRows
- array of selected table row objects
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"
row-key="id"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #bulk-actions="{ selectedRows }">
<KButton
appearance="danger"
:disabled="!selectedRows.length"
>
Delete ({{ selectedRows.length }} items selected)
</KButton>
</template>
</KTableView>
row-expanded
Slot for passing custom content that will be revealed once user expands one of the table rows when rowExpandable
prop is true
.
Slot props:
row
- table row objectheaders
- array of table headers objects to be passed to the nested table. See Expandable Rows section documentation for more detailscolumnWidths
- an object where each key represents a table column, and its corresponding value specifies the width to be used for that column in a nested table. Refer to Expandable Rows section documentation for more details
Expandable rows controls | 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"
:row-expandable="() => true"row-expandable
:headers="headers"
:pagination-attributes="{ totalCount: tableData.length }"
>
<template #row-expanded="{ row }">
<div>
<KCopy
:text="String(row.id)"
badge
badge-label="ID:"
/>
<div>
Joined on:
<KBadge appearance="info">
{{ new Date() }}
</KBadge>
</div>
<div>
Email verification status:
<KBadge :appearance="row.emailVerified ? 'success' : 'danger'">
{{ row.emailVerified ? '' : 'Not' }} Verified
</KBadge>
</div>
</div>
Lorem ipsum odor amet...
</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).
row-select
Emitted when user interacts with checkboxes in bulk actions column. Payload is array of selected table row objects.
update:row-expanded
Emitted when row is expanded or collapsed (when rowExpandable
prop is true
). Payload is object of type RowExpandPayload
.
interface RowExpandPayload {
row: Record<string, any>
expanded: boolean
}