DataGrid - Admin Components

Note: This component is available since Medusa v2.21.0.

The DataGrid component shows an editable spreadsheet-like grid whose values are bound to a react-hook-form form. The Medusa Admin uses it to bulk-edit variant prices and inventory quantities.

Code
1import {2  DataGrid,3  createDataGridHelper,4} from "@medusajs/dashboard/components"

The grid supports keyboard navigation, range selection, copying and pasting across cells, and undo and redo.


Example#

Create the grid's columns with createDataGridHelper, then pass your form to the grid's state prop:

src/admin/routes/variants/page.tsx
1import {2  DataGrid,3  createDataGridHelper,4} from "@medusajs/dashboard/components"5import { useForm } from "react-hook-form"6
7const columnHelper = createDataGridHelper<8  Variant,9  VariantsFormValues10>()11
12const VariantsPage = ({ variants }) => {13  const form = useForm<VariantsFormValues>({14    defaultValues: { variants },15  })16
17  const columns = [18    columnHelper.column({19      id: "title",20      name: "Title",21      header: "Title",22      cell: (context) => (23        <DataGrid.ReadonlyCell context={context}>24          {context.row.original.title}25        </DataGrid.ReadonlyCell>26      ),27    }),28    columnHelper.column({29      id: "sku",30      name: "SKU",31      header: "SKU",32      type: "text",33      field: (context) =>34        `variants.${context.row.index}.sku`,35      cell: (context) => (36        <DataGrid.TextCell context={context} />37      ),38    }),39  ]40
41  return (42    <DataGrid43      columns={columns}44      data={variants}45      state={form}46    />47  )48}49
50export default VariantsPage

The field function returns the path of the form field that the cell edits. If it returns null, the cell isn't editable.


Type Arguments#

DataGrid accepts two type arguments:

  • TData: the type of a single row in the grid.
  • TFieldValues: the shape of the values in the react-hook-form form that the grid edits. It defaults to FieldValues.

You rarely set them explicitly. TypeScript infers TData from the columns and data props, and TFieldValues from the state prop:

Code
1import { useForm } from "react-hook-form"2import { HttpTypes } from "@medusajs/framework/types"3
4type PricesForm = {5  variants: Record<string, Record<string, number>>6}7
8const form = useForm<PricesForm>()

Passing that form as state sets TFieldValues to PricesForm, and typing the columns sets TData:

Code
1const columnHelper = createDataGridHelper<2  HttpTypes.AdminProductVariant,3  PricesForm4>()

createDataGridHelper takes the same two type arguments, so set them there and the grid infers the rest:

Code
1<DataGrid2  columns={columns}3  data={variants}4  state={form}5/>

To set the type arguments explicitly, pass them when you use the component:

Code
1<DataGrid<HttpTypes.AdminProductVariant, PricesForm>2  columns={columns}3  data={variants}4  state={form}5/>

Props#

DataGrid accepts the DataGridProps type, which extends DataGridRootProps:

Loading...

Cell Components#

DataGrid has the following sub-components to render a column's cells. Each of them accepts a context prop, which is the cell context that the column's cell function receives:

Component

Description

DataGrid.TextCell

Edits the cell's value in a single-line text input.

DataGrid.MultilineCell

Edits the cell's value in a multi-line text input.

DataGrid.ExpandableTextCell

Edits long text. The user can expand the cell into a modal.

DataGrid.NumberCell

Edits the cell's value in a number input. It also accepts the min and max props.

DataGrid.CurrencyCell

Edits a price. It also accepts a code prop, which is the currency's code.

DataGrid.BooleanCell

Edits the cell's value with a checkbox. It also accepts a disabled prop.

DataGrid.ReadonlyCell

Shows its children in a cell that the user can't edit.


createDataGridHelper#

createDataGridHelper returns a typed helper whose column method defines a grid column. It accepts two type parameters: the type of a row, and the type of the form's values.

Code
1const columnHelper = createDataGridHelper<2  Variant,3  VariantsFormValues4>()

For example, the following column shows a variant's title in an editable text cell:

Code
1columnHelper.column({2  id: "title",3  name: "Title",4  header: "Title",5  field: (context) =>6    `variants.${context.row.index}.title`,7  type: "text",8  cell: (context) => (9    <DataGrid.TextCell context={context} />10  ),11})

The header and cell properties accept either a string or a function. The function receives a context object that you pass to the cell component, which uses it to read and write the cell's value.

The column method accepts an object with the following properties:

Loading...

createDataGridPriceColumns#

createDataGridPriceColumns returns a price column for each of the passed currencies and regions. Use it to let the user edit prices for many currencies and regions at once.

Code
1import {2  createDataGridPriceColumns,3} from "@medusajs/dashboard/components"4import { useTranslation } from "react-i18next"5
6const { t } = useTranslation()7
8const priceColumns = createDataGridPriceColumns<9  Variant,10  VariantsFormValues11>({12  currencies: ["usd", "eur"],13  regions,14  pricePreferences,15  getFieldName: (context, value) =>16    `variants.${context.row.index}.prices.${value}`,17  t,18})

It accepts an object with the following properties:

Loading...

  • Data Table: a read-only table for a list of records.
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
⇧↵