Skip to main content

Fragment Computed Values

Fragment computed values let AppConfig derive primitive values before fragment view fields and constraints are applied. Use them when a fragment needs small declarative decisions such as responsive line counts, focused colors, clamped artwork sizes, or constraint margins based on cell size.

Computed values live in a fragment's _dataMap.computed array and are referenced from view fields as exact computed.name strings.

Fragment computed value flow

Computed values derive primitive fields from runtime inputs, then feed exact computed.name view fields, status styles, and numeric constraint arguments.

{
"cells": {
"adaptiveCard": {
"$supportsDataMap": true,
"width": 640,
"height": 260,
"views": {
"base": [
{
"id": "titleLabel",
"subType": "Label",
"text": "${data.title}",
"width": 360,
"height": 72,
"wrap": "computed.titleWrap",
"maxLines": "computed.titleLines"
}
],
"normal": {},
"focused": {
"titleLabel": {
"color": "computed.titleColor"
}
}
},
"_dataMap": {
"view": {},
"data": {},
"fn": {},
"computed": [
{ "name": "isWide", "fn": "compare", "args": ["cell.width", "gt", 400] },
{ "name": "titleLines", "fn": "select", "args": ["computed.isWide", 2, 1] },
{ "name": "titleWrap", "fn": "select", "args": ["computed.isWide", true, false] },
{ "name": "titleColor", "fn": "select", "args": ["focus", "#ff3b30", "#ffffff"] }
]
}
}
}
}

The feature is intentionally small: it evaluates numbers, strings, and booleans. It does not replace fragment callbacks for measurement, host-side behavior, async data, or multi-view side effects.

Evaluation Model

Computed variables are evaluated in declaration order each time the fragment runtime calls applyFragmentComputed.

The current runtime applies computed values for:

  • DynamicCell fragments when item data is applied and when the view status changes.
  • CollectionView header fragments when header row data is applied.
  • FragmentView when data is updated and when view status is applied.

After evaluation, the resolved values are stored on the fragment as computedValues. The fragment provider then substitutes exact computed.name strings in fragment view maps and status styles.

Computed values also flow into fragment constraints. Constraint arguments that expect numbers can use computed.name, which is useful for margins, insets, and aspect ratios.

Declaration Shape

Each computed variable has this shape:

{
name: string;
fn: 'compare' | 'select' | 'clamp' | 'min' | 'max' | 'multiply' | 'add' | 'subtract' | 'divide';
args: Array<number | string | boolean>;
}

Names must be unique inside the fragment. A computed value can reference a value declared earlier in the same array with computed.otherName, but it cannot reference a later value.

References

Computed arguments support these references:

ReferenceResult
computed.nameA previously declared computed value.
data.path.to.valueA primitive value from the current item or FragmentView data object.
cell.widthThe current fragment host width, or 0 when unavailable.
cell.heightThe current fragment host height, or 0 when unavailable.
focus1 when the status is Focused or FocusSelected; otherwise 0.
screen.widthDevice resolution width, or 0 when unavailable.
screen.heightDevice resolution height, or 0 when unavailable.
safeArea.insets.topDevice safe-area top inset, or 0 when unavailable.
safeArea.insets.rightDevice safe-area right inset, or 0 when unavailable.
safeArea.insets.bottomDevice safe-area bottom inset, or 0 when unavailable.
safeArea.insets.leftDevice safe-area left inset, or 0 when unavailable.

data.* references must resolve to a number, string, or boolean. Missing data, object values, and array values fail evaluation.

View geometry references such as poster.right or titleLabel.width are not allowed in computed arguments. Use fragment constraints for child-to-child geometry.

Functions

FunctionArgsResult
compare[left, operator, right]Boolean comparison. Operators: eq, ===, ne, !==, gt, >, gte, >=, lt, <, lte, <=. Equality can compare any primitive; ordered comparisons require numbers.
select[condition, whenTrue, whenFalse]Returns one of two values. The condition must be a boolean or number.
clamp[value, min, max]Number constrained between min and max.
min[value, ...values]Smallest number. Requires at least one argument.
max[value, ...values]Largest number. Requires at least one argument.
multiply[left, right, ...values]Product of all numeric arguments.
add[left, right, ...values]Sum of all numeric arguments.
subtract[left, right]Numeric subtraction.
divide[left, right]Numeric division. Division by zero fails evaluation.

Numeric functions require finite numbers after references have been resolved.

Binding View Fields

A view field can use a computed value when the entire field value is an exact computed.name string.

{
"id": "poster",
"subType": "Poster",
"width": "computed.posterWidth",
"visible": "computed.posterVisible"
}

Computed values are not interpolated inside longer strings or arrays. Use computed.posterWidth, not "${computed.posterWidth}", "width: computed.posterWidth", or [0, "computed.y"].

When AppConfig resolves a fragment with $supportsDataMap, exact computed references are moved into the fragment data map's view section. At runtime only those fields are updated by computed substitution.

Status styles can also use computed values:

{
"views": {
"focused": {
"titleLabel": {
"color": "computed.titleColor"
}
}
}
}

Using Computed Values In Constraints

Fragment constraints can use computed values only in numeric argument positions. This works for margins, insets, and aspect ratios.

{
"_dataMap": {
"view": {},
"data": {},
"fn": {},
"computed": [
{ "name": "margin", "fn": "select", "args": ["focus", 24, 12] },
{ "name": "isWide", "fn": "compare", "args": ["cell.width", "gt", 500] },
{ "name": "ratio", "fn": "select", "args": ["computed.isWide", 1.7777777778, 1.3333333333] }
],
"constraints": [
{ "viewId": "titleLabel", "property": "x", "fn": "pin", "args": ["poster", "left", "right", "computed.margin"] },
{ "viewId": "poster", "property": "height", "fn": "aspectRatio", "args": ["computed.ratio"] }
]
}
}

String-only constraint arguments cannot be computed. For example, pin requires the referenced view and edge arguments to stay literal strings.

Common Patterns

Use computed values for cell-size responsive fields:

{
"computed": [
{ "name": "rawPosterWidth", "fn": "multiply", "args": ["cell.width", 0.34] },
{ "name": "posterWidth", "fn": "clamp", "args": ["computed.rawPosterWidth", 120, 280] }
]
}

Use them for focus-aware presentation:

{
"computed": [
{ "name": "titleColor", "fn": "select", "args": ["focus", "#ff3b30", "#ffffff"] },
{ "name": "posterVisible", "fn": "select", "args": ["focus", true, false] }
]
}

Use them for item-data decisions:

{
"computed": [
{ "name": "badgeRawWidth", "fn": "multiply", "args": ["data.priority", 24] },
{ "name": "badgeWidth", "fn": "clamp", "args": ["computed.badgeRawWidth", 56, 128] }
]
}

Failure Cases

Computed evaluation fails when:

  • a variable is missing name
  • two variables use the same name
  • a variable references computed.name before that value has been declared
  • a data.* reference does not resolve to a primitive value
  • a numeric function receives a non-number or non-finite number
  • divide receives 0 as its divisor
  • a computed argument uses view geometry such as poster.right
  • a constraint uses computed.name in a string-only argument position

Keep computed variables close to the fields they serve and keep names specific. If a value needs child measurement, asynchronous state, or coordinated updates across several nodes, use fragment callbacks instead.