Relation Data Range
Relation data range scripts restrict which target records users can select from a search, multi_search, or foreign_key field.
Use this interaction when the selectable records depend on the source field, current form, row context, current user, or a business rule such as "only active products" or "only customers in the current department".
Configure A Relation Data Range Script
- Open Work > Forms
- Open the form that contains the source relation field
- Go to Field Design
- Select a
search,multi_search, orforeign_keyfield - In the field settings panel, open Relation Data Scope
- Select a Studio script and, when needed, a specific script file
- Save the field
The script is bound to the source field. Do not configure this rule on the target form's page events.
Script Function
type RelationDataRangePayload = {
schema: 'soln.runtime-context/v1';
source: {
type: 'relation_data_range';
scope: 'main' | 'child';
fieldApiName: string | null;
targetForm: { id: string; apiName: string; name: string | null };
};
form: { id: string; apiName: string; name: string | null } | null;
record: RuntimeRecord | null;
draft: { data: Record<string, unknown> } | null;
selection: { records: RuntimeRecord[]; childRows: RuntimeChildRow[] };
child: RuntimeChildContext | null;
input: {
search: { keyword: string; batchKeywords: string[]; field: string };
};
result: unknown | null;
runtime: RuntimeMetadata;
};
export default async function main(payload: RelationDataRangePayload) {
return {
ok: true,
effects: [
{
type: 'relationDataFilter',
condition: {
logic: 'and',
children: [
{
field: 'status',
operator: 'eq',
value: 'active',
},
],
},
},
],
};
}
Payload
| Field | Type | Description |
|---|---|---|
schema | 'soln.runtime-context/v1' | Shared runtime context version |
source.type | 'relation_data_range' | Identifies the relation data range source |
source.scope | 'main' | 'child' | Whether the source field belongs to the main form or a child table |
source.fieldApiName | string | null | Source relation field API name |
source.targetForm | RuntimeFormRef | Target form identity |
form | RuntimeFormRef | null | Source form identity |
record | RuntimeRecord | null | Current persisted record when available |
draft.data | Record<string, unknown> | Current main-form draft values |
child.row.data | Record<string, unknown> | Current child-row draft values for child scope |
selection.childRows | RuntimeChildRow[] | Child rows available to this execution |
input.search.keyword | string | Current search keyword in the selection dialog |
input.search.batchKeywords | string[] | Batch search keywords when the selector performs batch lookup |
input.search.field | string | Target search field used by the selector |
Response
Return a relationDataFilter condition. The condition fields must use target-form field API names, not source-form field names or display labels.
The runtime combines this condition with the user's active selector filter using and.
Effect Response
return {
ok: true,
effects: [
{
type: 'relationDataFilter',
condition: {
logic: 'and',
children: [
{ field: 'so_product_type', operator: 'eq', value: 'standard' },
],
},
},
],
};
Direct Response
The runtime also accepts direct forms when the script only needs to return a condition:
return {
relationDataFilter: {
condition: {
logic: 'and',
children: [
{ field: 'so_product_type', operator: 'eq', value: 'standard' },
],
},
},
};
return {
condition: {
logic: 'and',
children: [
{ field: 'so_product_type', operator: 'eq', value: 'standard' },
],
},
};
Example: Active Products Only
export default async function main(payload) {
if (
payload?.schema !== 'soln.runtime-context/v1' ||
payload?.source?.type !== 'relation_data_range'
) {
return { ok: true };
}
return {
ok: true,
effects: [
{
type: 'relationDataFilter',
condition: {
logic: 'and',
children: [
{
field: 'so_status',
operator: 'eq',
value: 'active',
},
],
},
},
],
};
}
Notes
- Bind the script on the source
search,multi_search, orforeign_keyfield - Use target-form field API names inside
condition.children - Use
payload.draft.datafor main-form values andpayload.child.row.datafor current child-row values - Read selector input from
payload.input.search; do not add custom top-level payload properties - Do not place this rule on the target form's page-load event