Skip to content

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
html
<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).

ts
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 if hideLabel was true; you can set hideLabel parameter to false to show the label). KTableView will automatically render the actions dropdown button with an icon and you simply need to provide dropdown items via the action-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.

ts
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
vue
<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.

html
<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.

An error occurred

Data cannot be displayed due to an error.

html
<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
html
<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.

ts
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
html
<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
html
<KTableView
  :row-attrs="(row) => { return { 'data-testid': `row-${row.id}` } }"
  :data="tableData"
  :headers="headers"
  :pagination-attributes="{ totalCount: tableData.length }"
/>

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:

ts
interface RowLink {
  /** RouteLocationRaw or url string for row link */
  to?: RouteLocationRaw | string
  /** Target for row link */
  target?: '_self' | '_blank' | '_parent' | '_top'
}
vue
<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:

ts
{
  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
html
<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
html
<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:

ts
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
html
<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

No Data

There is no data to display.

html
<KTableView 
  :data="[]"
  :headers="headers"
/>

Set the following props to handle empty state:

  • emptyStateTitle - Title text for empty state
  • emptyStateMessage - Message for empty state
  • emptyStateIconVariant - Icon variant for empty state (see KEmptyState component props)
  • emptyStateActionMessage - Button text for empty state action
  • emptyStateActionRoute - Route for empty state action
  • emptyStateButtonAppearance - Appearance of empty state action button. See KButton appearance 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.

No Workspaces exist

Adding a new Workspace will populate this catalog.

html
<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.

An error occurred

Data cannot be displayed due to an error.

html
<KTableView
  error
  :data="tableData"
  :headers="headers"
/>

Set the following properties to customize the error state:

  • errorStateTitle - Title text for the error state
  • errorStateMessage - Message for the error state
  • errorStateActionMessage - Button text for the error state action
  • errorStateActionRoute - Route for the error state action

A error-action-click event is emitted when error state action button is clicked.

Something went wrong

Error loading data.

html
<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
html
<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 object
  • rowKey - table row index
  • rowValue - 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
html
<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
html
<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
html
<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 object
  • rowKey - 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
html
<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
html
<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
html
<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:

ts
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).

Released under the Apache-2.0 License.