formState holds the data that all the fields of a form share. Each expression gets it as a parameter:
Function("model", "formState", "field", `return ${expression};`);
model holds the answers of the user for one scope. formState holds data that is not part of the answers: the state of the application, the responses of the data-fetch components, the errors from the integrations, and the language of the user.
The portal writes formState. A form reads it. Do not write to formState from an expression.
When the user submits the application, the portal sends the contents of formState with the application data, in the field applicationFormState. It first removes the two functions, translate and getTranslation. All the other keys go to the server.
Therefore formState is not a private area. Do not put data in it. Read it only.
Four keys give almost all the use in the services that are live now.
APPLICATION_STATE holds the state of the application as text. Forms compare it with 'PENDING_RESUBMISSION' to find an application that an officer sent back to the citizen.
Use it to show a field, or to make a field read-only, only during a resubmission:
"expressions": {
"hide": "formState?.APPLICATION_STATE !== 'PENDING_RESUBMISSION'"
}
The state is text, not a boolean. Compare it with a value. Do not use it as a condition on its own.
A data-fetch component writes its response to FETCHED_DATA. The key is the key of the field that made the request:
formState.FETCHED_DATA[FIELD_KEY]
For a field in a repeater, the portal adds the key of the repeater and the index of the row:
formState.FETCHED_DATA[REPEATER_KEY][ROW_INDEX][FIELD_KEY]
The portal makes the response flat and then builds it again, therefore the shape of the object follows the shape of the response of the integration.
Use FETCHED_DATA to read in one field a value that a different field received:
"expressions": {
"hide": "!formState?.FETCHED_DATA?.institutionFetch?.data"
}
Two rules apply:
An integration that fails writes an error to globalErrors. The key is the key of the field that made the request. The object holds a message, the field, a timestamp, and a type.
"expressions": {
"hide": "!(formState?.globalErrors?.['VALIDATE_SHAREHOLDER_NATIONAL_ID'] && model?.SHAREHOLDER_DOCUMENT === 'NID')"
}
Use this key to show a message, or a manual-entry field, only when an automatic check did not give a result.
globalError, in the singular, holds the most recent error only. It stays available for the forms that were built before globalErrors. Use globalErrors in new forms.
getTranslation is a function. It takes a translation key and gives the text in the language of the user. All the portals give this function.
Send each label that you build in an expression through this function:
label: formState?.getTranslation(option.label);
Custom Expressions shows the full pattern for a dropdown.
Translate the labels. Do not translate the values. A value goes to the workflow and to the integrations, therefore it must stay the same in all languages.
The second function, translate, gives the translation service of Angular directly. Use getTranslation.
The portal also writes these keys. No service that is live now reads them from an expression. Read this table before you use one, because the platform can change a key that no form uses.
| Key | Contents |
|---|---|
FETCHED_OPTIONS_DATA |
Options that a fetch component received for a dropdown. |
FETCHED_COLUMNS_DATA |
Column definitions that a fetch component received for a table. |
FETCHED_METADATA |
Data about a response that is not part of the response. |
RFA_FLAGGED_FIELDS |
The fields that an officer marked for correction. |
JOURNEY_FEEDBACKS |
The comments of an officer for a journey service. |
ALLOW_EDITING_ALL_FIELDS |
true lets the user change all the fields during a resubmission. |
APPLICANT_TYPE |
The type of applicant, for example an individual or a business. |
APPLICANT_BUSINESS_NAME |
The name of the business, when a business makes the application. |
APPLICANT_BUSINESS_ID |
The identifier of the business. |
APPLICANT_USER_ID |
The identifier of the user account that makes the application. |
LOCALE |
The language code of the user. |
Read only. Do not write to formState from an expression. The portal is the owner of these keys.
Always use optional chaining. The portal builds formState in steps. A key that is available at the end of the form is not available at the start.
Compare with a value. Most keys hold text, not a boolean. formState?.APPLICATION_STATE is true for all the states.
Do not put private data in formState. The portal sends it with the application.
Use the keys of this page only. A key that you invent is empty at each pass, and the expression that reads it always gives the same result.
Custom Expressions How to write an expression that has more than one statement.
Form Rules Model scope, parent chain depth, and the rules for all expressions.
Older pages kept in this wiki for this topic: