Multi-Select
Choose many values using the card picker UI—same option mechanics as Select (static optionConfigs, dynamic APIs, dependents, recursive nested forms). Submissions store a string array.
Overview
The Multi-Select field lets respondents toggle multiple choices from one question. Selected values appear as removable badges above a responsive grid of option cards. The saved value is always an array of strings (each entry matches an option's stored value).
Everything that applies to Select for sourcing options also applies here: optionConfigs, plain options strings, isDynamic + dataSource, parent-aware URLs via dependsOn, and optional nestedForm payloads per option.
Note: Use schema type multi_select (underscore) — the docs URL slug uses multi-select for navigation only.
Properties
Note: Submission keys follow each field's id. Dependent fields reference parents by dataSource.dependsOn using that parent's id.
| Property | Type | Default | Description |
|---|---|---|---|
| id | string | — | Unique field identifier. |
| type | string | "multi_select" | Discriminator (underscore, not hyphen). |
| label | string | — | Human-readable label shown above the field or step heading. |
| required | boolean | false | When true, the form cannot submit without a value. |
| isHidden | boolean | false | Hides the field from respondents (may still store defaults). |
| isDisabled | boolean | false | Renders the field read-only. |
| instruction | string | undefined | Help text shown below the label (not the same as placeholder). |
| optionConfigs | OptionConfig[] | undefined | Choices as { label, value, nestedForm? }; nested sections render for every selected option that defines nestedForm. |
| optionConfigs[].nestedForm | NestedForm | undefined | { id, name?, fields } — same recursive rules as Select. |
| options | string[] | [] | Label-only fallbacks when optionConfigs omitted (stored value equals label). |
| isDynamic | boolean | false | Fetch choices via dataSource. |
| dataSource.url | string | — | HTTP endpoint; brace placeholders resolved using parentValuePath when dependent. |
| dataSource.method | "GET" | "POST" | GET | HTTP verb. |
| dataSource.path | string | "" | Dot-path to array inside JSON response. |
| dataSource.valueField | string | — | Property used as option value. |
| dataSource.labelField | string | — | Property shown as label. |
| dataSource.headers | object | undefined | Extra request headers. |
| dataSource.body | object | undefined | POST JSON template. |
| dataSource.dependsOn | string | undefined | Parent field id for cascading reloads / URL substitution. |
| dataSource.parentValuePath | string | undefined | Token replaced inside url (e.g. path "id" replaces "{id}"). |
| dataSource.parentValueParam | string | undefined | POST-only body merge key for parent value. |
Static options
Provide optionConfigs so each chip maps to a stable machine value.
{
"id": "c21bdd9f-7f90-4f1c-9f33-111111111111",
"type": "multi_select",
"label": "Preferred stack",
"required": false,
"placeholder": "Choose technologies",
"options": ["React", "Vue"],
"optionConfigs": [
{ "label": "React", "value": "react" },
{ "label": "Vue", "value": "vue" },
{ "label": "Svelte", "value": "svelte" }
]
}Dynamic options
Identical response-shaping rules as dynamic Select: array at path, map rows via valueField / labelField.
{
"id": "d22bdd9f-7f90-4f1c-9f33-222222222222",
"type": "multi_select",
"label": "Quotes (demo)",
"required": false,
"options": ["Option 1", "Option 2"],
"isDynamic": true,
"dataSource": {
"url": "https://dummyjson.com/quotes",
"path": "quotes",
"valueField": "id",
"labelField": "author",
"method": "GET"
}
}Dependent options
Child multi-selects wait until dependsOn resolves, then rewrite URL placeholders exactly like dependent Select fields.
{
"id": "e33bdd9f-7f90-4f1c-9f33-333333333333",
"type": "multi_select",
"label": "Follow-up picks",
"required": false,
"options": ["Option 1", "Option 2"],
"isDynamic": true,
"dataSource": {
"url": "https://dummyjson.com/quotes/{id}",
"path": "",
"valueField": "id",
"labelField": "author",
"dependsOn": "d22bdd9f-7f90-4f1c-9f33-222222222222",
"parentValuePath": "id"
}
}Nested option forms
Attach nestedForm to any static optionConfigs row. Unlike Select/Radio (single nested panel), Multi-Select renders one bordered section per selected option that owns a nested form—so choosing three branching answers can surface three independent mini-forms at once.
Inner fields may themselves be selects or checkbox groups with their own nesting; recursion limits follow whatever you author in JSON.
Use Cases by Pattern
Static multi-select
- “Select all that apply” surveys with compact chip summaries
- Service add-ons where each SKU maps to its own nested follow-up fields
- Admin tags or scopes modeled as finite enums shipped with the form
Dynamic / dependent multi-select
- Bulk entitlement pickers sourced from CRM arrays filtered by account id
- Incident categories downloaded live, narrowed after a primary lookup field
Nested multi-select
- Cross-functional intake forms needing parallel detail blocks per chosen department
- Conference workshops where multiple sessions each open their own waiver checklist