Skip to main content

Computed Field Usage

Computed fields add derived fields to a dataset. They can calculate values directly with an expression, or define a field in the dataset and let a chart binding Studio script write values into it.

Common scenarios:

ScenarioDescription
Row-level calculationCalculate amount, duration, status, or labels from the current record or joined records
Shared business logicKeep repeated calculation rules in the dataset so charts can reuse the same field
External metric enrichmentQuery Soln aggregated chart data first, then use a script to add metrics from third-party systems, member directory, approval data, or another service
Chart post-processingCalculate targets, completion rates, forecasts, or warning values from aggregated chart data

Usage Flow​

Computed fields are configured in two places:

  1. Add the computed field in Datasets, and choose its name, data type, and value source
  2. Configure the field role and aggregation in Fields And Metadata
  3. Use the computed field in chart field slots
  4. If the value source is Studio Script, configure a chart Binding Script, then set match fields and assignments
  5. Click Run Script, check the preview, and save the chart

Expression fields are calculated during dataset preview and chart query. Script-backed fields only define the field structure in the dataset; their values are written by the chart binding script after the chart query returns aggregated data.

Add A Computed Field In A Dataset​

In the dataset configuration page:

  1. Select Dataset Properties
  2. Click the Custom Column icon in the middle panel
  3. Enter the Field Name
  4. Choose the Data Type
  5. Choose the Value Source
  6. Configure the expression, or save the field as a script-backed field
  7. Save the computed field
SettingDescription
Field NameDisplay name used in charts. Use a business-friendly name
Data TypeResult type. Supported types include string, number, date, datetime, and boolean
Value SourceDetermines whether the value is calculated by an expression or written by a chart binding script

After saving, the computed field appears in the dataset field list. You can continue editing its display name, role, aggregation, and enabled status in Fields And Metadata.

Value Source​

Expression​

Use an expression when the value can be derived from the current dataset row. It can use fields from the primary form, joined forms, and common functions. Expressions are best for fixed rules that depend on row data.

Examples:

ScenarioExample
Amount calculationActual Amount = Order Amount - Discount
Time calculationHandling Time = Completed At - Created At
Status judgmentOverdue = Due Date is earlier than today
Group labelCustomer Tier = A/B/C by accumulated amount

Expression fields can be checked in dataset preview. Preview the dataset before saving when possible.

Studio Script​

Use a Studio script when the result cannot be calculated from a row expression alone. After choosing Studio Script, the dataset saves a script-backed computed field. Dataset preview does not calculate this value directly; chart Binding Script writes the value during chart query.

Script-backed fields are useful for:

ScenarioDescription
Third-party metricsQuery targets, budgets, exchange rates, inventory, ad spend, or other external values by chart category
Soln data enrichmentUse Studio SDK to query form records, members, departments, organizations, approvals, or IAM data
Multi-step rulesUse a script for multiple queries, branches, mapping tables, weights, or algorithms
Aggregated calculationCalculate completion rate, target gap, or forecast after the chart has already grouped by region, month, or owner
Metric card valueReturn one global value, such as target amount, external balance, or real-time exchange rate

Prefer expressions when the calculation only depends on current-row fields. Use Studio scripts when the calculation depends on aggregated chart data, another system, or complex runtime logic.

Role And Aggregation​

After saving a computed field, configure its role in Fields And Metadata.

RoleUsage
DimensionCategories, groups, axes, colors, or filters
MeasureNumeric statistics, axes, size, metric cards, or targets

Script-backed computed fields are usually measures, and their data type should be number. Chart binding scripts currently write values only into numeric computed measures.

Aggregation controls how multiple script result rows are merged when they match the same chart point:

AggregationScript Binding Rule
NoneAllows only one result. Multiple matched results cause a duplicate-result error
SumAdds matched values
AverageAverages matched values
MaxUses the largest matched value
MinUses the smallest matched value
CountCounts matched values that can be converted to numbers
Distinct CountCounts distinct matched numeric values

None is only available for script-backed computed fields. It is useful when each chart point must match exactly one script result. Regular fields and expression fields do not use None as an aggregation.

Bind A Script In A Chart​

When a chart uses a script-backed computed field, configure Binding Script in the chart editor.

Steps:

  1. Open the chart editor
  2. Put the script-backed computed field into a measure slot, such as Y-axis measure, metric card measure, or target measure
  3. Open Binding Script on the left
  4. Select a Studio script
  5. Configure Match Fields when needed
  6. In Assignments, choose the computed field and enter the script result field
  7. Click Run Script
  8. Check the preview and save the chart

Execution order:

  1. The chart queries the Soln dataset using dimensions, measures, filters, and base-record limits
  2. The aggregated query result is passed to the Studio script as chartData
  3. The Studio script returns an array or { rows: [...] }
  4. The system matches script rows to chart points
  5. The system writes script result fields into the mapped script-backed computed fields
  6. The chart preview renders with the updated data

Script Payload​

Binding scripts are Studio scripts. The entry function follows the same pattern as the Soln SDK documentation:

export default async function main(
_payload: StudioScriptRuntimeContextPayload,
_context: StudioScriptContext
) {
return { rows: [] };
}

Chart binding scripts always receive soln.runtime-context/v1. Dataset identity is in payload.source, while query options and chart data are in payload.input:

PathDescription
payload.source.datasetIdDataset ID used by the chart
payload.source.dimensionsDataset field keys used as chart dimensions
payload.source.measuresDataset field keys used as chart measures
payload.input.conditionCurrent chart filter condition
payload.input.timeGrainTime grain, such as day, week, or month
payload.input.baseRecordTimeFieldTime field used for base-record selection, usually updatedAt or createdAt
payload.input.chartDataAggregated chart data, including categories, field metadata, series, and rows

Common chartData shape:

type BindingChartData = {
categories: string[];
dimensions: Array<{
key: string;
name: string;
apiName: string;
dataType: string;
}>;
measures: Array<{
key: string;
name: string;
apiName: string;
dataType: string;
aggregationType: string;
valueSource: string | null;
}>;
series: Array<{
fieldKey: string;
fieldName: string;
aggregationType: string;
groupFieldKey?: string | null;
groupValue?: string | null;
data: Array<number | null>;
}>;
rows: Array<Record<string, unknown>>;
};

chartData.rows is the most useful part for scripts. Each row represents one chart point or one category-and-group combination, and includes these system fields:

FieldDescription
__rowIndexRow index of the chart point. Use it when returning values by row
__categoryIndexPosition of the current category in categories
__categoryCurrent category name

Rows also include the current chart dimension and measure fields. Keys use dataset field keys.

Script Return Format​

Return rows from the script. These formats are supported:

return [
{ __rowIndex: 0, targetAmount: 1000 },
{ __rowIndex: 1, targetAmount: 2000 },
];
return {
rows: [
{ province: 'Guangdong', targetAmount: 1000 },
{ province: 'Zhejiang', targetAmount: 2000 },
],
};
return {
data: [
{ month: '2026-01', targetAmount: 5000 },
],
};

When returning an object, the row array can be named rows, items, or data. Each row should be a plain object.

Match Fields And Assignments​

Match Fields decide which chart point receives each script result row.

SettingDescription
Dataset FieldField from the current chart data, such as province, month, or owner
Script Result FieldField in the script result row, such as province, month, or ownerName

When match fields are configured, the system compares values from chartData.rows with values from returned script rows. Only matched rows write values back to chart points.

Assignments decide which script result field writes into which computed field.

SettingDescription
Computed FieldNumeric computed measure whose value source is Studio Script
Script Result FieldReturned field to write, such as targetAmount, budget, or rate

If assignments are not configured, the system tries to read a same-name value using the computed field key or API Name. Explicit assignments are recommended because they make the chart configuration easier to understand.

Single Result Without Match Fields​

If no match fields are configured and the script returns exactly one row, the system writes that row to chart point 0 by default. This is useful for metric cards or single-row totals.

Example:

export default async function main(_payload: StudioScriptRuntimeContextPayload) {
return {
rows: [
{ targetAmount: 100000 },
],
};
}

If the chart has multiple categories, configure match fields or return __rowIndex explicitly.

Example: Calculate By Chart Row​

This example reads chartData.rows and calculates a target value from each chart point's current sales value.

type BindingInput = {
chartData: {
rows: Array<Record<string, unknown>>;
};
};

export default async function main(payload: StudioScriptRuntimeContextPayload) {
const input = payload.input as BindingInput;
return {
rows: input.chartData.rows.map((row) => {
const sales = Number(row['t0.amount'] || 0);

return {
__rowIndex: row.__rowIndex,
targetAmount: Math.round(sales * 1.2),
};
}),
};
}

Chart configuration:

SettingValue
AssignmentsComputed field: Target Amount; script result field: targetAmount
Match FieldsNot needed, because the script returns __rowIndex

Example: Match External Results By Province​

This example fits a chart grouped by province. The script returns one target amount per province.

type BindingInput = {
chartData: {
rows: Array<Record<string, unknown>>;
};
};

export default async function main(payload: StudioScriptRuntimeContextPayload) {
const input = payload.input as BindingInput;
const provinces = input.chartData.rows.map((row) => String(row['t0.province'] || ''));

const targetByProvince: Record<string, number> = {
Guangdong: 120000,
Zhejiang: 90000,
Jiangsu: 85000,
};

return {
rows: provinces.map((province) => ({
province,
targetAmount: targetByProvince[province] || 0,
})),
};
}

Chart configuration:

SettingValue
Match FieldsDataset field: Province; script result field: province
AssignmentsComputed field: Target Amount; script result field: targetAmount

If the script returns data at a finer grain than the chart, such as multiple city rows for one province, the system uses the computed field's aggregation to merge rows. For target amount, Sum is usually the right aggregation.

Example: Query Soln Data With SDK​

Scripts can use studioScriptContext to call Soln SDK. See Soln SDK for detailed capabilities.

The example below reads province targets from a target form and writes them back to the chart.

type BindingInput = {
chartData: {
rows: Array<Record<string, unknown>>;
};
};

export default async function main(
payload: StudioScriptRuntimeContextPayload,
context: StudioScriptContext
) {
const input = payload.input as BindingInput;
const provinceNames = Array.from(
new Set(input.chartData.rows.map((row) => String(row['t0.province'] || '')))
).filter(Boolean);

const targetRecords = await context.form.list({
formApiName: 'sales_targets',
limit: 100,
condition: {
logic: 'and',
children: [
{
field: 'province',
operator: 'in',
value: provinceNames,
},
],
},
});

return {
rows: targetRecords.items.map((record) => ({
province: record.data.province,
targetAmount: record.data.targetAmount,
})),
};
}

Configure province as the match field, then assign targetAmount to the target amount computed field.

Example: Call Third-Party Data​

If the current Studio script runtime allows external requests, use the runtime-supported HTTP capability to call third-party systems. A common pattern is to read categories from chartData.rows, then request external data in batch.

type BindingInput = {
chartData: {
rows: Array<Record<string, unknown>>;
};
};

export default async function main(
payload: StudioScriptRuntimeContextPayload,
context: StudioScriptContext
) {
const input = payload.input as BindingInput;
const months = input.chartData.rows.map((row) => String(row['t0.month'] || ''));

const response = await context.http.requestJson({
url: 'https://example.com/api/monthly-targets',
method: 'POST',
json: { months },
});

if (!response.ok) {
throw new Error('MONTHLY_TARGET_REQUEST_FAILED');
}

const result = response.data as {
rows: Array<{ month: string; targetAmount: number }>;
};

return {
rows: result.rows,
};
}

When an external request fails, either throw an error so chart preview shows a failure, or use try/catch to return empty rows or defaults. See the script error handling section in Soln SDK.

Troubleshooting​

The Script Field Has No Value In Dataset Preview​

This is expected. Script-backed computed fields are written by chart binding scripts. Dataset preview does not run chart binding scripts. Use Run Script in the chart editor to preview values.

The Script Field Has No Value In The Chart​

Check these items:

  1. The chart uses the dataset that contains the script-backed computed field
  2. The computed field is numeric and is placed into a measure slot
  3. A Studio script is selected in Binding Script
  4. The assignment result field matches the field returned by the script
  5. Match fields can find the same values in chartData.rows and returned script rows
  6. The script returns an array, { rows: [...] }, { items: [...] }, or { data: [...] }

Multiple Script Results Cause An Error​

When aggregation is None, each chart point can match only one script result. If one chart point should merge multiple rows, change the computed field aggregation to Sum, Average, Max, Min, Count, or Distinct Count.

Expression Or Studio Script?​

Use this rule of thumb:

ConditionRecommendation
Only current-row fields are neededUse an expression
Primary and joined fields are enough for a fixed calculationUse an expression
Aggregated chart categories, groups, or measures are neededUse a Studio script
Other Soln records, members, departments, approvals, or IAM data are neededUse a Studio script and Soln SDK
Third-party system data is neededUse a Studio script

Best Practices​

  • Use business-friendly field names, such as Target Amount, Completion Rate, or External Inventory
  • Choose number as the data type for script-backed measures
  • Prefer expressions when they can solve the calculation cleanly
  • Keep returned script field names stable, such as targetAmount, budgetAmount, or completionRate
  • Configure assignments explicitly in charts instead of relying on same-name matching
  • Set the computed field aggregation before returning multiple rows for one chart point
  • Query in batches inside scripts instead of making one request per chart point
  • Handle external request failures, empty values, and timeouts so chart preview remains understandable