Dependent dropdowns (cascading editors)

Country → State → City. Editing one level resets downstream levels; each cell's dropdown options come from the row's upstream value.

const REGIONS: Record<string, Record<string, string[]>> = {
  USA:     { California: ['SF', 'LA', 'San Diego'], Texas: ['Austin', 'Dallas'] },
  Germany: { Bavaria: ['Munich', 'Nuremberg'],     Berlin: ['Berlin'] },
}

const columns: ColumnDef<typeof features, Region>[] = [
  { field: 'country', editorType: 'list',
    editorOptions: () => Object.keys(REGIONS) },
  { field: 'state', editorType: 'list',
    editorOptions: (row) => Object.keys(REGIONS[row.country] ?? {}) },
  { field: 'city', editorType: 'list',
    editorOptions: (row) => REGIONS[row.country]?.[row.state] ?? [] },
]

The (row) => options form is what makes the cascade work: every cell re-computes its options from the row's current value at edit time.

Reset downstream on upstream change

When country changes, the row's state and city may now be invalid. Catch the cell change and snap them to a sane default:

<SvGrid
  {data} {columns} features={features}
  onCellValueChange={(e) => {
    if (!api) return
    if (e.columnId === 'country') {
      const newCountry = String(e.newValue)
      const firstState = Object.keys(REGIONS[newCountry] ?? {})[0] ?? ''
      const firstCity  = (REGIONS[newCountry]?.[firstState] ?? [])[0] ?? ''
      api.setCellValue(e.rowIndex, 'state', firstState)
      api.setCellValue(e.rowIndex, 'city',  firstCity)
    } else if (e.columnId === 'state') {
      const row = rows[e.rowIndex]
      const firstCity = (REGIONS[row.country]?.[String(e.newValue)] ?? [])[0] ?? ''
      api.setCellValue(e.rowIndex, 'city', firstCity)
    }
  }}
  onApiReady={(next) => (api = next)}
/>

Live in demo 68 (Dependent dropdowns)

More examples

Data validation (dropdowns)

Excel Data Validation on a plain : Status / Priority / Owner / Sprint columns are list-constrained (double-click for a dropdown), and Estimate must be a whole number 0-40. Four cells arrive invalid and light up red with the reason as a tooltip; fix one and it clears live. Dropdowns are editorType:list + editorOptions; the flag is the declarative validate() hook.

Open the live example: Data validation (dropdowns) (Spreadsheet)

See also

Live examples

  • Data validation (dropdowns) - Excel Data Validation on a plain <SvGrid>: Status / Priority / Owner / Sprint columns are list-constrained (double-click for a dropdown), and Estimate must be a whole number 0-40. Four cells arrive invalid and light up red with the reason as a tooltip; fix one and it clears live. Dropdowns are editorType:list + editorOptions; the flag is the declarative validate() hook.
  • Dependent dropdowns - Cascade editors: Country → State → City. Each level computes its options from the row's upstream value; changing Country resets State + City.