customdropdowndatafetchpaginated
A paginated dropdown that fetches options through the integration engine. It can also re-fetch when another form field changes.
A paginated dropdown that fetches options through the integration engine. It can also re-fetch when another form field changes.
This component always requires triggerType: 'FIELD_LISTENER' in props, even when no other field drives the fetch. This prop starts the initial data load. Without it, the dropdown never loads any options.
Read Form Rules before using this component — keys, labels, required fields, expressions, visibility, and validation all follow shared conventions.
When to use
- Options must come through the integration engine (an
endpointCodeis required) - The list is large enough to need pagination
- The available options depend on the value of another field in the form (optional — this component also works with no dependency, as a plain integration-backed lookup)
When NOT to use
Instead of customdropdowndatafetchpaginated, use… | For… |
|---|---|
customdropdownpaginated | A direct backend API call (no integration endpoint) |
customdropdown | Small static option lists |
customcascadingdropdowns | Hard-wired province → district → sector hierarchies |
Props
| 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. |
url | string | required | Integration engine API URL (typically /integration/v1/fetch/sync). |
endpointCode | string | required | Integration endpoint code sent in the request payload. |
dataset.dataField | string | required | Dot-notation path to the array of options inside the integration response. |
dataset.pagination | boolean | required | Must be true to enable load-more scrolling. |
required | boolean | required | Always false. The expression controls the runtime value. |
defaultRequired | boolean | required | true for required fields, false for optional ones. |
useBaseUrl | boolean | optional | Prepend the API gateway base URL to url. Set true for production. |
dataset.httpMethod | string | optional | 'GET' or 'POST'. Default 'POST'. |
dataset.params | object | optional | Extra params merged into the integration request payload. |
dataset.headers | object | optional | Extra HTTP headers. |
dataset.totalPagesKey | string | optional | Path to total pages in the response. Default 'totalPages'. |
dataset.currentPageKey | string | optional | Path to current page in the response. Default 'currentPage'. |
dataset.pageKey | string | optional | Param name for page number in the request. Default 'page'. |
dataset.sizeKey | string | optional | Param name for page size in the request. Default 'size'. |
dataset.pageStart | number | optional | Initial page number. Default 0. |
dataset.searching | boolean | optional | Shows the search box and sends a search query to the API as the user types. Default true — the search box shows unless you set this to false explicitly. |
dataset.searchLocal | boolean | optional | When true, filters already-loaded items client-side instead of calling the API. Do not combine with searching: true. |
dataset.searchKey | string | optional | Param name for the search value in API requests. Default 'search'. |
triggerType | string | required | Always 'FIELD_LISTENER'. This is what makes the component fetch data at all — not just for re-fetching on a dependency change. Leave it out and the dropdown never loads any options. |
payloadKey | string | optional | Field key whose value re-triggers the fetch when it changes. Leave unset for a plain lookup with no dependency — the component still fetches once, on load. |
useMultiplePayloadKeys | boolean | optional | When true, use payloadKeyMappings instead of payloadKey. |
payloadKeyMappings | array | optional | Multiple payload params — each { key, sourceField, isStatic, staticValue }. Set staticValue when isStatic: true; a mapping with isStatic: true and only sourceField sends undefined for that param. |
debounceTime | number | optional | Milliseconds to debounce field-listener re-fetches. Default 500. |
populates | array | optional | { valueKey, targetKey } mappings to auto-fill downstream fields on selection. |
placeholder | string | optional | Ghost text shown before a value is selected. |
multiple | boolean | optional | Allows selecting multiple values. |
virtualScroll | boolean | optional | Enables virtual scrolling. |
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"]. |
Examples
Minimal — doctor lookup via integration, no dependency
triggerType: 'FIELD_LISTENER' is set even though nothing depends on another field. Without it, the component never fetches and the dropdown stays empty.
{
"key": "DOCTOR",
"type": "customdropdowndatafetchpaginated",
"props": {
"label": "Doctor",
"required": false,
"defaultRequired": true,
"bindLabel": "fullName",
"bindValue": "id",
"url": "/integration/v1/fetch/sync",
"endpointCode": "LIST_DOCTORS",
"useBaseUrl": true,
"triggerType": "FIELD_LISTENER",
"dataset": {
"params": { "page": 0, "size": 20 },
"dataField": "doctors",
"pageStart": 0,
"pagination": true
}
},
"expressions": {
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Doctor is required."
}
}
}Full example — country lookup that re-fetches when gender changes
{
"key": "APPLICANT_NATIONALITY_2",
"type": "customdropdowndatafetchpaginated",
"props": {
"url": "/integration/v1/fetch/sync",
"label": "Nationality",
"required": false,
"defaultRequired": true,
"bindLabel": "name",
"bindValue": "countryCode",
"useBaseUrl": true,
"placeholder": "Select country",
"triggerType": "FIELD_LISTENER",
"endpointCode": "RDB_COUNTRIES_FETCH",
"useMultiplePayloadKeys": true,
"payloadKeyMappings": [{ "key": "searchkey", "sourceField": "APPLICANT_GENDER_2" }],
"dataset": {
"params": { "page": 0, "size": 20 },
"dataField": "data.data",
"pageStart": 1,
"searching": true,
"pagination": true,
"totalPagesKey": "data.totalElements"
}
},
"expressions": {
"hide": "!(model?.APPLICANT_DOCUMENT_TYPE === 'Passport')",
"props.disabled": "model?.IS_RESUBMITTED",
"props.required": "!(field?.props?.hideField || field?.hide) && field?.props?.defaultRequired"
},
"validation": {
"messages": {
"required": "Nationality is required."
}
}
}Common mistakes
- Omitting
triggerType: 'FIELD_LISTENER'— this is the most common cause of an empty dropdown. Without it, the component never calls the API, even with a validendpointCodeand no dependency field. - Omitting
endpointCode— the component silently makes no requests and the list stays empty. - Omitting
dataset.pagination: true— load-more never triggers. - Confusing
props.urlwithdataset.url— this component reads the URL fromprops.url, notdataset.url. - Using
customdropdowndatafetchpaginatedwhen noendpointCodeexists — usecustomdropdownpaginatedinstead. - Setting
dataset.searchLocal: trueanddataset.searching: truesimultaneously — they serve different purposes; pick one. - Setting
dataset.searching: falseto hide the search box, then forgetting it defaults totrueelsewhere — check every field that should not show a search box. - Setting
isStatic: truein apayloadKeyMappingsentry but supplyingsourceFieldinstead ofstaticValue— the sent value isundefined.
Checklist
-
keyisUPPER_SNAKE_CASEand unique across the entire form -
props.labelis present, unique, and correctly cased - Field is nested at the correct depth:
sections > formly-group > block > customdropdowndatafetchpaginated -
required: falseis set (nevertrue) -
defaultRequiredis set (trueorfalse) -
expressions["props.required"]is present with the exact required expression -
urlis the integration endpoint path (typically/integration/v1/fetch/sync);useBaseUrl: truein production -
endpointCodeis set -
triggerType: 'FIELD_LISTENER'is set, even when the field has no dependency -
bindLabelandbindValuematch real keys in the response option objects -
dataset.dataFieldmatches the response array path -
dataset.pagination: true - If a dependency drives the fetch,
payloadKeyorpayloadKeyMappingsis set; if a mapping isisStatic: true, it carriesstaticValue, notsourceField -
searchingandsearchLocalare not bothtrue -
validation.messages.requiredis present when the field is required
customdropdown
A single-select or multi-select dropdown. Supports static option lists, admin dataset endpoints, and integration endpoints.
customdropdownpaginated
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.