A dropdown that loads options in pages from a direct backend API. Use when the list is too large to load at once but does not need to go through the integration engine.
Read Form Rules before using this component — keys, labels, required fields, expressions, visibility, and validation all follow shared conventions.
customdropdown (~100+ items)Instead of customdropdownpaginated, use… |
For… |
|---|---|
customdropdown |
Small static option lists (~under 100 items) |
customdropdowndatafetchpaginated |
Options sourced through the integration engine (requires endpointCode) |
customcascadingdropdowns |
Dependent dropdowns (e.g. province → district → sector) |
| Prop | Type | Required? | Description |
|---|---|---|---|
label |
string |
required | Display label; must be unique across the form. |
bindLabel |
string |
required | Key in each option object used as the display text. |
bindValue |
string |
required | Key in each option object used as the stored value. Use "" to store the whole object. |
dataset.url |
string |
required | API endpoint that returns paginated options. |
dataset.dataField |
string |
required | Dot-notation path to the array of options inside the response. |
dataset.params |
object |
required | Initial query/body params; must include a page key set to the starting page (usually 0). |
dataset.totalPagesKey |
string |
required | Key in the response that holds the total page count. |
dataset.currentPageKey |
string |
required | Key in the response that holds the current page number. |
dataset.pagination |
boolean |
required | Must be true to enable the "load more" scroll trigger. |
required |
boolean |
required | Always false. The expression controls the runtime value. |
defaultRequired |
boolean |
required | true for required fields, false for optional ones. |
dataset.httpMethod |
string |
optional | 'GET' or 'POST'. Defaults to the base dropdown setting. |
dataset.headers |
object |
optional | Extra HTTP headers to include. |
dataset.searching |
boolean |
optional | When true, sends a search query to the API as the user types. |
dataset.searchField |
string |
optional | Param name for the search value. Defaults to bindLabel. |
placeholder |
string |
optional | Ghost text shown before a value is selected. |
multiple |
boolean |
optional | Allows selecting multiple values. |
virtualScroll |
boolean |
optional | Enables virtual scrolling for very long lists. |
useBaseUrl |
boolean |
optional | Prepend the API gateway base URL to dataset.url. |
min |
number |
optional | Minimum number of selectable items when multiple: true. |
max |
number |
optional | Maximum number of selectable items when multiple: true. |
hideField |
boolean |
optional | Hides the field and excludes its value from submission. Toggle via expressions["props.hideField"]. |
{
"key": "PARCEL",
"type": "customdropdownpaginated",
"props": {
"label": "Land Parcel",
"required": false,
"defaultRequired": true,
"bindLabel": "parcelCode",
"bindValue": "id",
"useBaseUrl": true,
"dataset": {
"url": "/admin/v1/parcels",
"dataField": "data.content",
"params": { "page": 0, "size": 20 },
"totalPagesKey": "data.totalPages",
"currentPageKey": "data.number",
"pagination": true
}
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Parcel is required."
}
}
}
{
"key": "PARCEL",
"type": "customdropdownpaginated",
"props": {
"label": "Land Parcel",
"required": false,
"defaultRequired": true,
"placeholder": "Search or scroll to select a parcel",
"bindLabel": "parcelCode",
"bindValue": "id",
"useBaseUrl": true,
"dataset": {
"url": "/admin/v1/parcels",
"dataField": "data.content",
"httpMethod": "GET",
"params": { "page": 0, "size": 20 },
"totalPagesKey": "data.totalPages",
"currentPageKey": "data.number",
"pagination": true,
"searching": true,
"searchField": "parcelCode"
}
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Parcel is required."
}
}
}
dataset.pagination: true — the "load more" trigger never fires and only the first page loads.dataset.totalPagesKey or dataset.currentPageKey — pagination breaks because the component cannot track page state.page in dataset.params — the API receives no page parameter on the first request.customdropdownpaginated when the list has fewer than ~100 items — use customdropdown instead; paginated adds unnecessary complexity.bindValue: "" when a string ID is needed — an empty bindValue stores the whole option object, not the ID.key is UPPER_SNAKE_CASE and unique across the entire formprops.label is present, unique, and correctly casedsections > formly-group > block > customdropdownpaginatedrequired: false is set (never true)defaultRequired is set (true or false)expressions["props.required"] is present with the exact required expressionbindLabel and bindValue match real keys in the response option objectsdataset.pagination: truedataset.params includes a starting page valuedataset.totalPagesKey and dataset.currentPageKey match the response shapevalidation.messages.required is present when the field is required