Form State
The contents of formState, the third identifier in scope in a form expression. This page gives the keys that the portal writes, the data that each key holds, and the rules for their use.
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.
What the portal sends
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.
Keys that forms use today
Four keys give almost all the use in the services that are live now.
APPLICATION_STATE
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.
FETCHED_DATA
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:
- The data is not available until the fetch is complete. Always use optional chaining, and always give a result for the condition in which the data is missing.
- The portal removes the entry when the field that made the request becomes invalid. A value that was available at one pass can be absent at the next pass.
globalErrors
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
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.
Keys that the portal writes but no form reads
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. |
Rules
- Read only. Do not write to
formStatefrom an expression. The portal is the owner of these keys. - Always use optional chaining. The portal builds
formStatein 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_STATEis 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 JavaScript with more than one statement in a form expression. This page gives the rules for IIFE expressions and shows the approved patterns.
Validators
The full validator catalog — standard, date, file, multi-select, cross-field, repeater, and identity validators with their option shapes and message keys.