Skip to content

Core Props

Every prop <DataEditor /> accepts.

Prop Type Default
apiKey string Required
blockSubmitOnError boolean false
chat DataEditorChat
className string
columns DataEditorColumn[] Required
enableAddRow boolean true
enableAddSource boolean true
enableCreateColumn boolean true
enableDeleteRow "all" | "new" | false false
exportFormats DataEditorFormat[] | false All formats
headerHeight number 36
importFormats DataEditorFormat[] | false All formats
loadData (onChunk) => Promise<void>
locale string "en"
localStorage false | { licenseGrant?: boolean } { licenseGrant: true }
mode "modal" | "inline" "modal"
onClose () => void Modal mode only
onColumnMatch (headers, columns) => map
onComplete (result) => void | Promise<void>
onError (error: UpdogError) => void
onValueMatch (valuesToMatch) => map
open boolean Modal mode only
primaryKey keyof TRow | readonly (keyof TRow)[] Required
readonly boolean false
remoteSources RemoteSource[]
rowHeight number 34
rtl boolean false
sampleData Record<string, unknown>[]
synonyms { columns?, values? }
translations DataEditorTranslations
variant "editor" | "uploader" | "viewer" "editor"
Type string
Required Yes

Your Updog license key. The SDK validates it every time the editor opens.

<DataEditor apiKey="your-license-key" ... />
Type boolean
Default false

Disables the submit button while any row has a validation error. When false, errors are flagged but the user can still submit.

When set, submission is also blocked while remote checks are in flight (isAsyncValidating), so a value that is about to come back “already exists” cannot slip through. Remote checks give up after 60 seconds without activity, so this gating always releases. When unset (the default), in-flight checks never block submission and unresolved cells pass through as unverified.

<DataEditor blockSubmitOnError ... />
Type DataEditorChat<TRow>

Bring-your-own-AI chat. When provided, the editor shows a chat panel alongside the grid. You own the AI integration. The SDK hands you dataset context and renders the streamed response.

See Bring Your Own AI.

Type string

CSS class added to the wrapper element. Use for scoped styling overrides.

Type DataEditorColumn[]
Required Yes

The schema your app expects. Each column defines an id, a title, and optionally an editor, validators, a transformer, a formatter, and a filter.

See Columns for every column-level prop.

Type boolean
Default true

Controls whether users can add rows by hand. When true, the data sources panel shows an “Add row” button, and the row context menu offers Insert row above, Insert row below, and Duplicate row. When false, every one of those entry points is hidden, and the user edits existing rows or imports data instead.

<DataEditor enableAddRow={false} ... />
Type boolean
Default true

Controls whether the “Add data source” button appears in the data sources panel. When false, the button is hidden, and the panel no longer opens the add-source menu (import data, add row).

<DataEditor enableAddSource={false} ... />
Type boolean
Default true

Allow creating new columns for unmatched headers during import. When enabled, users can keep data from file columns that do not match your schema.

See enableCreateColumn.

Type "all" | "new" | false
Default false

Controls row deletion through the right-click context menu.

  • false disables deletion.
  • "new" allows deleting rows the user added by hand or imported.
  • "all" allows deleting any row.
<DataEditor enableDeleteRow="all" ... />
Type DataEditorFormat[] | false
Default All formats

Which file formats the user can export to. Set to false to disable export entirely.

<DataEditor exportFormats={["csv", "xlsx"]} ... />

See DataEditorFormat for the full list of formats.

Type number
Default 36

Header row height in pixels.

Type DataEditorFormat[] | false
Default All formats

Which file formats the user can import. Set to false to disable import entirely.

See importFormats.

Type (onChunk) => Promise<void>

Async function that feeds existing data into the editor. Called once when the editor opens. Call onChunk one or more times to stream rows in batches.

See Loading Data.

Type string
Default "en"

BCP 47 locale tag used to pick plural forms. It does not load translations and it does not switch the language.

See locale.

Type false | { licenseGrant?: boolean }
Default { licenseGrant: true }

Controls what the editor stores in localStorage. Set to false to switch off local storage entirely.

licenseGrant caches the license validation result so the editor skips re-validation on reload. It defaults to true. The grant is a signed token stored under the key updog_license_grant. See Data and Privacy for what it contains and what turning it off costs you.

Type "modal" | "inline"
Default "modal"

Rendering mode. "modal" wraps the editor in a full-screen dialog overlay. "inline" renders it directly in the DOM.

Type () => void
Required Modal mode only

Called when the user closes the modal (X button or Escape key). If the user has unsaved changes, the SDK shows a confirmation dialog before calling onClose.

Type (headers: string[], columns: DataEditorColumn[]) => Record<string, string | null>

Override column matching during import. Return a map of fileHeader to column ID. Unmapped or null entries fall back to built-in matching.

See onColumnMatch.

Type (result: DataEditorResult<TRow>) => void | Promise<void>

Called when the user clicks Submit. Receives the edited data grouped by source.

See Submitting.

Type (error: UpdogError) => void

Called when the SDK catches an internal error. The SDK recovers where it can. Use this for logging and monitoring.

See Error Handling.

Type (valuesToMatch: Record<string, ValueMatchInput>) => ValueMatchOutput

Override value matching for select columns during import. Return a map of column ID to imported-value pairs.

See onValueMatch.

Type boolean
Required Modal mode only

Controls modal visibility. You own the state.

Type keyof TRow | readonly (keyof TRow)[]
Required Yes

The column that uniquely identifies each row, like id or email.

<DataEditor<Employee> primaryKey="id" ... />

Pass a list when identity takes several columns together, such as a customer number that repeats across branches or a SKU that repeats across suppliers. An imported row merges into an existing row only when every listed column matches. A row with an empty value in any part of the key merges with nothing and is added as new.

<DataEditor<Customer> primaryKey={["branch", "customerNo"]} ... />

Values are compared after trimming surrounding whitespace. The comparison keeps case, so [email protected] and [email protected] are two different keys. Fold the case in a transformer on that column when the two should merge.

Type boolean
Default false

When true, hides all editing UI. The grid becomes view-only.

Type RemoteSource[]

Your own remote data sources, rendered as buttons on the upload step. You own the integration. The SDK renders the button and processes the result of fetch().

See remoteSources.

Type number
Default 34

Row height in pixels.

Type boolean
Default false

Enable right-to-left layout. Affects grid direction, text alignment, scrollbar position, and the column order in exported files.

See rtl.

Type Record<string, unknown>[]

Sample rows included in the Download Example file offered by the import wizard. When omitted, the SDK generates one generic example row from your column definitions.

See sampleData.

Type { columns?: Record<string, string[]>; values?: Record<string, string[]> }

Extra aliases layered on top of the built-ins, in two tables. columns feeds column matching, values feeds value matching. Each key is the canonical target, and the array lists the aliases.

See synonyms.

Type DataEditorTranslations

Override any UI string. Pass a partial object. Only the keys you provide are replaced. This is the prop that changes the language.

See Localization.

Type "editor" | "uploader" | "viewer"
Default "editor"

Controls the initial view. "editor" opens directly to the spreadsheet grid. "uploader" opens the file import wizard first, where the user uploads one or more files, maps columns, and fixes errors before continuing to the grid. "viewer" renders the grid on its own, with no filters sidebar, footer, or chat. It stays read-only whatever you pass to readonly.