Components

customdropdowndatafetchpaginated

A paginated dropdown that fetches options through the integration engine, optionally with dependency-driven re-fetching when other form fields change.

A paginated dropdown that fetches options through the integration engine, optionally with dependency-driven re-fetching when other form fields change.

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 endpointCode is required)
  • The list is large enough to need pagination
  • The available options depend on the value of another field in the form

When NOT to use

Instead of customdropdowndatafetchpaginated, use…For…
customdropdownpaginatedA direct backend API call (no integration endpoint)
customdropdownSmall static option lists
customcascadingdropdownsHard-wired province → district → sector hierarchies

Props

PropTypeRequired?Description
labelstringrequiredDisplay label; must be unique across the form.
bindLabelstringrequiredKey in each option object used as the display text.
bindValuestringrequiredKey in each option object used as the stored value.
urlstringrequiredIntegration engine API URL (typically /integration/v1/fetch/sync).
endpointCodestringrequiredIntegration endpoint code sent in the request payload.
dataset.dataFieldstringrequiredDot-notation path to the array of options inside the integration response.
dataset.paginationbooleanrequiredMust be true to enable load-more scrolling.
requiredbooleanrequiredAlways false. The expression controls the runtime value.
defaultRequiredbooleanrequiredtrue for required fields, false for optional ones.
useBaseUrlbooleanoptionalPrepend the API gateway base URL to url. Set true for production.
dataset.httpMethodstringoptional'GET' or 'POST'. Default 'POST'.
dataset.paramsobjectoptionalExtra params merged into the integration request payload.
dataset.headersobjectoptionalExtra HTTP headers.
dataset.totalPagesKeystringoptionalPath to total pages in the response. Default 'totalPages'.
dataset.currentPageKeystringoptionalPath to current page in the response. Default 'currentPage'.
dataset.pageKeystringoptionalParam name for page number in the request. Default 'page'.
dataset.sizeKeystringoptionalParam name for page size in the request. Default 'size'.
dataset.pageStartnumberoptionalInitial page number. Default 0.
dataset.searchingbooleanoptionalWhen true, sends a search query to the API as the user types.
dataset.searchLocalbooleanoptionalWhen true, filters loaded items client-side. Do not combine with searching: true.
dataset.searchKeystringoptionalParam name for the search value in API requests. Default 'search'.
triggerTypestringoptional'FIELD_LISTENER' — re-fetches whenever the dependency field(s) change.
payloadKeystringoptionalField key whose current value is passed as a payload param.
useMultiplePayloadKeysbooleanoptionalWhen true, use payloadKeyMappings instead of payloadKey.
payloadKeyMappingsarrayoptionalMultiple payload params — each { key, sourceField, isStatic, staticValue }.
debounceTimenumberoptionalMilliseconds to debounce field-listener re-fetches. Default 500.
populatesarrayoptional{ valueKey, targetKey } mappings to auto-fill downstream fields on selection.
placeholderstringoptionalGhost text shown before a value is selected.
multiplebooleanoptionalAllows selecting multiple values.
virtualScrollbooleanoptionalEnables virtual scrolling.
minnumberoptionalMinimum number of selectable items when multiple: true.
maxnumberoptionalMaximum number of selectable items when multiple: true.
hideFieldbooleanoptionalHides the field and excludes its value from submission. Toggle via expressions["props.hideField"].

Examples

Minimal — doctor lookup via integration

{
  "key": "DOCTOR",
  "type": "customdropdowndatafetchpaginated",
  "props": {
    "label": "Doctor",
    "required": false,
    "defaultRequired": true,
    "bindLabel": "fullName",
    "bindValue": "id",
    "url": "/integration/v1/data-fetch",
    "endpointCode": "LIST_DOCTORS",
    "useBaseUrl": true,
    "dataset": {
      "dataField": "doctors",
      "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 endpointCode — the component silently makes no requests and the list stays empty.
  • Omitting dataset.pagination: true — load-more never triggers.
  • Setting triggerType: 'FIELD_LISTENER' without setting payloadKey or payloadKeyMappings — the component triggers immediately without any dependency value.
  • Confusing props.url with dataset.url — this component reads the URL from props.url, not dataset.url.
  • Using customdropdowndatafetchpaginated when no endpointCode exists — use customdropdownpaginated instead.
  • Setting dataset.searchLocal: true and dataset.searching: true simultaneously — they serve different purposes; pick one.

Checklist

  • key is UPPER_SNAKE_CASE and unique across the entire form
  • props.label is present, unique, and correctly cased
  • Field is nested at the correct depth: sections > formly-group > block > customdropdowndatafetchpaginated
  • required: false is set (never true)
  • defaultRequired is set (true or false)
  • expressions["props.required"] is present with the exact required expression
  • url is the integration endpoint path; useBaseUrl: true in production
  • endpointCode is set
  • bindLabel and bindValue match real keys in the response option objects
  • dataset.dataField matches the response array path
  • dataset.pagination: true
  • If triggerType: 'FIELD_LISTENER', payloadKey or payloadKeyMappings is also set
  • searching and searchLocal are not both true
  • validation.messages.required is present when the field is required

On this page