# Computed Text _How to add and configure a Computed Text field in the {{Notebook}} Editor._ --- ## What This Field Does A Computed Text derives text from an expression over other fields in the form (and, for child records, fields on the record's parent) — for example, joining a site code and plot number, or classifying a measurement into 'Low' / 'Medium' / 'High'. The generated value is read-only for data collectors; they see the result but cannot edit it, and it updates automatically as the fields it references change. The field stays blank until every field its expression references has a usable value, so a partially filled form shows no result rather than a misleading one. ## Adding the Field To add this field, open the [ADD A FIELD dialog](../shared-settings/adding-a-field.md), navigate to the **TEXT** tab, and click the **Computed Text** card. Then click the **ADD FIELD** button in the lower right. ```{screenshot} field-types-design/computed-text-01-add-field.png :alt: Adding a Computed Text — the TEXT tab in the ADD A FIELD dialog :align: right :width: 100% ``` ## Configuring the Field Click the field's **grey header bar** to expand it and see its settings. For an overview of the settings shared by all fields — including Label, Helper Text, Field ID, and the field toolbar — see [Field Identity](../shared-settings/field-identity.md) and [Field Toolbar](../shared-settings/field-toolbar.md). Give the field a meaningful Label, review the auto-populated Field ID, and add any desired Helper Text. ```{screenshot} field-types-design/computed-text-02-configured.png :alt: Computed Text configuration in the {{Notebook}} Editor :align: right :width: 100% ``` ### Computed Text-Specific Settings The Computed Text's key feature is the **Expression** text area, which defines the generated text. Each referenced field is written by wrapping its Field ID in braces, and text is joined with the `&` operator, e.g. `{Site-Code} & '-' & {Plot}`. Below the expression, a searchable field picker lists the referenceable fields in the form; selecting one inserts that field's reference, which avoids typing the Field ID by hand. | Setting | What It Does | | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ | | **Expression** | A text area where you define the generated text using literals, operators, and field references in single-brace syntax (e.g., `{Site-Code} & '-' & {Plot}`). | | **Insert field** | A searchable picker of the referenceable fields in the form. Selecting one inserts its braced reference into the expression. | The expression is typed and checked when the {{notebook}} is designed — mixing types is reported as an error in the Editor. The overall expression must produce **text**. The operators are: - **Concatenation** (`&`) — joins text, e.g. `{Site-Code} & '-A'`. - **Arithmetic** (`+ - * / % ^`) — numbers only (useful inside conditions). - **Comparisons** (`< > <= >=`) — two numbers or two texts, producing true/false; equality (`==`, `!=`) requires matching types. - **Logic** (`&&`, `||`, `!`) — true/false values only. - **Conditionals** — a ternary `condition ? ifTrue : ifFalse`, with a true/false condition and same-typed branches. Ternaries can be nested to classify values, e.g. `{vegType} == 'hedge' ? ({vegHeight} < 3 ? 'Low' : 'High') : 'Medium'`. Number and checkbox fields can be referenced anywhere in the expression — only the final result must be text. Referenced fields are normally in the same form as the Computed Text; fields on the record's parent can also be referenced (see below). A Computed Text cannot reference another computed field or a Templated String in the same form. For record identifiers (HRIDs), use a [Templated String](templated-string.md) instead. ### Referencing Parent Record Values When the form is a child of another form (linked through a Child-relation Related Records field), the expression can reference fields on the record's parent by prefixing the Field ID with `_PARENT.`, e.g. `{_PARENT.Site-Code} & '-' & {Plot}`. An **Insert parent field** picker below the expression lists the available parent fields. Parent references are type checked like any other reference, and — unlike same-form references — may point at the parent's computed fields and Templated Strings, whose stored values are used. If a record has no parent, a parent reference has no value and the result stays blank, matching the behaviour for missing same-form values. The generated text is stored on save and re-derives whenever the record is next opened or saved; if the parent changes in the meantime, the stored value reflects the parent as of the record's last save. The same reference can be used in [field and section conditions](../../authoring/conditions.md). ### Referencing Linked Record Values When the form holds a [Related Records](../relationship-fields/related-records.md) field with a **Linked** relation that allows only a single link, the expression can reference fields on the linked record by joining the two Field IDs with a dot: `{Link-Field-ID.Field-ID}`. For example, with a Related Records field `Core-Calibration` linking one Calibration record, `{Core-Calibration.Cutter-ID} & '-' & {Sample-Code}` includes the linked record's cutter ID. An **Insert linked record field** picker below the expression lists the available fields. Linked record references are type checked against the linked form, and may point at the linked record's computed fields and Templated Strings, whose stored values are used. Fields that allow multiple links, and Child-relation fields, cannot be referenced this way (children reference their parent with `_PARENT.`); the editor reports these with a specific error. If nothing is linked, the reference has no value and the result stays blank. The value updates while editing whenever the link is changed, and otherwise re-derives when the record is opened or saved — if the linked record changes in the meantime, the stored value reflects it as of this record's last save. The same reference can be used in [field and section conditions](../../authoring/conditions.md). ### Referencing Notebook Metadata Values The expression can read a value from the {{notebook}}'s custom metadata (the custom fields on the Info panel in the {{Notebook}} Editor) using the `_METADATA.` prefix: `{_METADATA.Field-Name}`. An **Insert notebook metadata** picker below the expression lists the available fields. Every metadata value is text, so it can be joined with `&` and compared directly, e.g. `{_METADATA.season} & '/' & {Site-Code}`. If the {{notebook}} has no custom field with that name, the editor reports an error; at run time a missing value leaves the result blank. A custom field that an expression references cannot be removed from the Info panel until the expression is changed. ### Using Constants Mathematical constants such as `{_CONSTANT.PI}` can be used in any arithmetic inside the expression (for example within a conditional). See [Using Constants](../number-fields/computed-number-field.md#using-constants) in the Computed Number documentation for the full list. ### Shared Field Options Configure any of the shared field options as needed. For settings shared across all field types — including Annotation, Uncertainty, Conditions, Copy value to new records, and Display in child records — see [Field Options](../shared-settings/field-options.md). ## Tips - **Use the field picker to build expressions** rather than typing Field IDs by hand. Selecting a field inserts the exact braced reference, so you avoid typos and do not need to remember a field's ID. - **Nest ternaries for classifications** — thresholds like Low/Medium/High are a natural fit, as in the example above. - **The result stays blank until all referenced fields have values.** This is intentional — a partially complete record shows no value rather than a misleading partial calculation. - **Computed Texts are read-only for data collectors.** They see the generated text but cannot edit it, keeping the value consistent with its inputs. - **String comparisons are exact, including case.** `{vegType} == 'hedge'` will not match a value of `Hedge` — the expression takes the other branch with no error. When comparing against fixed values, prefer a Choice field for the input so the values are exact by construction.