QUI React Table

Column Definitions

A column def a configuration object that defines various aspects of a column in a table. It specifies how the data should be accessed, displayed, and interacted with in that column. They are responsible for:

  • Building the underlying data model that will be used for everything including sorting, filtering, grouping, etc.
  • Formatting the data model into what will be displayed in the table.
  • Creating header groups, headers, and footers.

Column Definition Categories

Column definitions are organized into three categories that describe and categorize different kinds of column definitions:

  • Accessor Columns
    • Accessor columns have an underlying data model which means they can be sorted, filtered, grouped, etc. This is the most common type of column.
  • Display Columns
    • Display columns do not have a data model which means they cannot be sorted, filtered, etc., but they can be used to display arbitrary content in the table like a row action button, checkbox, or expander.
  • Grouping Columns
    • Group columns are used to group other columns together. Since they don't have a data model, they can't be sorted or filtered. It's common to define a header or footer for a column group.

Column Helpers

At the end of the day, column definitions are just objects.

We export a createColumnHelper utility that simplifies the creation and configuration of column definitions. It provides a more structured and type-safe way to define columns, making your code cleaner and easier to manage, especially in TypeScript. If you set up your data and types correctly, the table will be able to infer the shape of your data and enforce that your column definitions are made correctly.

Here's an example of creating and using a column helper:

import {createColumnHelper, ColumnDef} from "@qui/react-table"
interface Person {
name: string
age: number
address: string
}
const columnHelper = createColumnHelper<Partial<Person>>()
const columns: ColumnDef<Partial<Person>, any>[] = [
columnHelper.accessor("name", {
header: "Name",
cell: (info) => <span>{info.getValue()}</span>,
}),
columnHelper.accessor("age", {
header: "Age",
cell: (info) => <span>{info.getValue()}</span>,
enableSorting: true,
}),
columnHelper.accessor("address", {
header: "Address",
cell: (info) => <span>{info.getValue()}</span>,
}),
]

Detailed Breakdown

Name Column

  • Header: The text "Name" will be displayed in the header of this column.
  • Accessor: Uses the name key from the data objects to determine what to display in each cell.
  • Cell: Renders the value of name inside a <span> element for each cell.

Age Column

  • Header: The text "Age" will be displayed in the header of this column.
  • Accessor: Uses the age key from the data objects.
  • Cell: Renders the value of age inside a <span> element for each cell.
  • Enable Sorting: Sorting is enabled, allowing users to sort the table by age.

Address Column

  • Header: The text "Address" will be displayed in the header of this column.
  • Accessor: Uses the address key from the data objects.
  • Cell: Renders the value of address inside a <span> element for each cell.

Creating Accessor Columns

Data columns are unique in that they must be configured to extract primitive values for each item in your data array.

There are three ways to do this:

  1. If your items are objects, use an object-key that corresponds to the value you want to extract.
  2. If your items are nested arrays, use an array index that corresponds to the value you want to extract.
  3. Use an accessor function that returns the value you want to extract.

Object Keys

If each of your items is an object with the following shape:

interface Person {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}

You could extract the firstName value like so:

columnHelper.accessor("firstName")
// OR
const column = {
accessorKey: "firstName",
}

Deep Keys

If each of your items is an object with the following shape:

interface Person {
name: {
first: string
last: string
}
info: {
age: number
visits: number
}
}

You could extract the first value like so:

columnHelper.accessor("name.first", {
id: "firstName",
})
// OR
const column = {
accessorKey: "name.first",
id: "firstName",
}

Accessor Functions

If each of your items is an object with the following shape:

interface Person {
firstName: string
lastName: string
age: number
visits: number
status: string
progress: number
}

You could extract a computed full-name value like so:

columnHelper.accessor((row) => `${row.firstName} ${row.lastName}`, {
id: "fullName",
})
// OR
const column = {
id: "fullName",
accessorFn: (row) => `${row.firstName} ${row.lastName}`,
}

TIP

Remember, the accessed value is crucial for sorting, filtering, and other operations. Ensure your accessor function returns a primitive value that can be effectively manipulated. If you return a non-primitive value, such as an object or array, you'll need the appropriate filter, sort, or grouping functions to handle it.