ConfigurableDataTable - Admin Components

Note: 

The ConfigurableDataTable component shows a data table whose columns, filters, and saved views the user configures from the Medusa Admin. The Medusa Admin uses it on list pages that support view configurations, such as the products, customers, and regions lists.

Use the ConfigurableDataTable component when you have the view configuration feature enabled and want to provide a customizable table experience for your users.

Code
1import {2  ConfigurableDataTable,3} from "@medusajs/dashboard/components"

Unlike DataTable, you don't pass columns or data to ConfigurableDataTable. Instead, you pass an adapter that tells the component which entity to show and how to fetch its records. The component then resolves the columns and filters from the Medusa backend and applies the user's saved view.


Example#

Create the adapter with the createTableAdapter utility, then pass it to the component:

src/admin/routes/brands/page.tsx
1import {2  ConfigurableDataTable,3} from "@medusajs/dashboard/components"4import { createTableAdapter } from "@medusajs/dashboard/lib"5import { useBrands } from "../../hooks/brands"6
7const adapter = createTableAdapter<Brand>({8  entity: "brands",9  entityName: "Brands",10  useData: (fields, params) => {11    const { brands, count, isLoading, isError, error } =12      useBrands({ fields, ...params })13
14    return { data: brands, count, isLoading, isError, error }15  },16  getRowHref: (row) => `/brands/${row.id}`,17})18
19const BrandsPage = () => {20  return (21    <ConfigurableDataTable22      adapter={adapter}23      heading="Brands"24      subHeading="Manage your brands"25      actions={[{ label: "Create", to: "create" }]}26    />27  )28}29
30export default BrandsPage

Type Argument#

ConfigurableDataTable accepts one type argument, TData, which is the type of a single row in the table.

You set it on the adapter rather than on the component. createTableAdapter infers TData from the data that your useData hook returns, and the component picks it up from the adapter prop:

Code
1import { createTableAdapter } from "@medusajs/dashboard/lib"2import { useProducts } from "@medusajs/dashboard/hooks"3
4const adapter = createTableAdapter({5  entity: "products",6  useData: (fields, params) => {7    const { products, count, isLoading, isError, error } =8      useProducts({ fields, ...params })9
10    return { data: products, count, isLoading, isError, error }11  },12})

TData is now HttpTypes.AdminProduct, so the adapter's other functions receive typed rows:

Code
1const adapter = createTableAdapter({2  entity: "products",3  useData: (fields, params) => {4    // ...5  },6  getRowId: (product) => product.id,7  getRowHref: (product) => `/products/${product.id}`,8})

To set the type argument explicitly, pass it to createTableAdapter. This is useful when your hook's return type is wider than the rows you show:

Code
1const adapter = createTableAdapter<Brand>({2  entity: "brands",3  useData: (fields, params) => {4    // ...5  },6})

Props#

The component accepts the ConfigurableDataTableProps type:

Loading...
Was this page helpful?
Ask Bloom
For assistance in your development, use Claude Code Plugins or Docs MCP server in Cursor, VSCode, etc...FAQ
What is Medusa?
How can I create a module?
How can I create a data model?
How do I create a workflow?
How can I extend a data model in the Product Module?
Recipes
How do I build a marketplace with Medusa?
How do I build digital products with Medusa?
How do I build subscription-based purchases with Medusa?
What other recipes are available in the Medusa documentation?
Chat is cleared on refresh
Line break
⇧↵