Skip to main content

Dynamic Options (API calls)

React-Forminate provides powerful dynamic options loading for select fields (with future support for checkboxes and other field types). This feature allows you to fetch options from APIs automatically, with support for dependencies between fields, pagination, and response transformation.

Basic Usage

Simple API Fetch

{
fieldId: "countries",
type: "select",
dynamicOptions: {
endpoint: "https://api.example.com/countries",
fetchOnInit: true // Load options when form mounts
}
}

With Response Transformation

{
fieldId: "users",
type: "select",
dynamicOptions: {
endpoint: "https://api.example.com/users",
transformResponse: (res) =>
res.map(user => ({ label: user.name, value: user.id })),
fetchOnInit: true
}
}

Dynamic Options Configuration

Core Properties

PropertyTypeDescriptionDefault
endpointstringAPI endpoint URL (supports template variables like {{fieldId}})required
methodstringHTTP method"GET"
dependsOnstring | string[]Field IDs this field depends onundefined
paramsobjectQuery parameters (values can reference other fields)undefined
headersobjectRequest headersundefined
transformResponsefunctionTransforms API response to option formatundefined
resultPathstringPath to extract data from nested responseundefined
fetchOnInitbooleanFetch options when component mountsfalse
paginationobjectPagination configurationundefined

Dependent Fields

Create chained selects where options depend on another field's value:

{
fieldId: "state",
type: "select",
dynamicOptions: {
dependsOn: "country", // Watches country field
endpoint: "https://api.example.com/states",
params: {
country: "country" // Uses value from country field
}
}
}

Pagination

For large datasets, enable pagination:

{
fieldId: "products",
type: "select",
dynamicOptions: {
endpoint: "https://api.example.com/products",
pagination: {
limit: 10,
pageMode: "page", // or "skip"
pageKey: "page", // query param name
limitKey: "limit",
startPage: 1
}
}
}

Advanced Features

Response Transformation

Convert API responses to the expected format:

transformResponse: (res) => {
return res.data.items.map(item => ({
label: `${item.firstName} ${item.lastName}`,
value: item.id,
metadata: {
department: item.dept
}
}));
}

Nested Data Extraction

Extract data from complex responses:

{
dynamicOptions: {
endpoint: "https://api.example.com/data",
resultPath: "results.items" // Extracts res.results.items
}
}

Template Variables

Use field values in URLs:

{
fieldId: "userDetails",
type: "select",
dynamicOptions: {
endpoint: "https://api.example.com/users/{{userId}}/details",
dependsOn: "userId"
}
}

Complete Example

import { DynamicForm } from "react-forminate";

const ProductForm = {
formId: "productForm",
fields: [
{
fieldId: "category",
type: "select",
label: "Product Category",
dynamicOptions: {
endpoint: "https://api.example.com/categories",
fetchOnInit: true,
transformResponse: (res) =>
res.map(cat => ({ label: cat.name, value: cat.id }))
}
},
{
fieldId: "product",
type: "select",
label: "Product",
dynamicOptions: {
dependsOn: "category",
endpoint: "https://api.example.com/products",
params: {
categoryId: "category" // Uses value from category field
},
pagination: {
limit: 20,
pageMode: "page",
maxPage: 5
},
transformResponse: (res) =>
res.map(prod => ({
label: prod.title,
value: prod.id,
price: prod.price
}))
}
},
{
fieldId: "variant",
type: "select",
label: "Variant",
dynamicOptions: {
dependsOn: ["category", "product"], // Multiple dependencies
endpoint: "https://api.example.com/products/{{product}}/variants",
transformResponse: (res) =>
res.variants.map(v => ({ label: v.name, value: v.id }))
}
}
]
};

const ProductSelector = () => (
<DynamicForm
formId={ProductForm.formId}
formData={ProductForm}
onSubmit={(values) => console.log(values)}
/>
);
Clicky