Data sources & loading
Declare the data outside the form. Reference it by key inside any field. JavaScript handles requests; core consumes the results.
Define a source
{
"apis": {
"backend": {
"baseUrl": "https://api.example.com/",
"timeoutMs": 30000
}
}
}{
"countries": {
"api": "backend",
"endpoint": "countries",
"resultPath": "/data",
"schema": {
"type": "array",
"items": {
"type": "object",
"properties": {
"value": {
"type": "string"
},
"label": {
"type": "string"
}
},
"required": [
"value",
"label"
]
}
}
}
}Pass the first object as config and the second as dataSources. resultPath is a JSON Pointer: /data extracts that property; /data/0/value extracts the first item’s value. The optional response schema checks the extracted/mapped result. Supported types are string, number, integer, boolean, null, object, and array with an items schema.
Bind a field
{
"type": "select",
"key": "country",
"bindings": {
"options": {
"source": "countries"
}
}
}{
"type": "select",
"key": "region",
"bindings": {
"options": {
"source": "regions",
"params": {
"country": {
"ref": "country"
}
}
}
}
}Use an options binding for select/radio options and a value binding for field values. Bindings name a source; params use { value: scalar } for literals or { ref: fieldKey } for field references. Value bindings support apply: initial (default) or live; options bindings always track their source. Referenced fields drive dependent requests after core accepts the schema. Select options are value/label objects, while radio values are booleans.
Loading and retry
Loading disables the affected field. Selects show a spinner and failed sources show an error with a retry control. New generations cancel or ignore stale responses. Rules and validation run after the result is integrated.
Dependent select options clear invalid selections. selectFirstOption: true chooses the first option when an empty selection needs a default; it defaults to false. Valid values from a reopened draft take priority over automatic defaults.
Own the transport
const config = {
apis: { backend: { baseUrl: 'https://api.example.com/',
headers: () => ({ Authorization: 'Bearer ' + getToken() }) } },
request: async (request) => {
// Use request.url, method, headers, body, credentials and signal.
// Context identifies source/upload/submit/save/i18n requests.
return { data: await yourClient(request) }
},
}
<Tungsten schema={schema} config={config} dataSources={sources} onSubmit={save} />Credentials belong in application configuration rather than exported schemas. Endpoints are relative to the configured base URL. Timeouts default to 30 seconds. An override receives cancellation signals and must return a data envelope. Non-idempotent operations are not blindly retried.