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.

KeyContents
FETCHED_OPTIONS_DATAOptions that a fetch component received for a dropdown.
FETCHED_COLUMNS_DATAColumn definitions that a fetch component received for a table.
FETCHED_METADATAData about a response that is not part of the response.
RFA_FLAGGED_FIELDSThe fields that an officer marked for correction.
JOURNEY_FEEDBACKSThe comments of an officer for a journey service.
ALLOW_EDITING_ALL_FIELDStrue lets the user change all the fields during a resubmission.
APPLICANT_TYPEThe type of applicant, for example an individual or a business.
APPLICANT_BUSINESS_NAMEThe name of the business, when a business makes the application.
APPLICANT_BUSINESS_IDThe identifier of the business.
APPLICANT_USER_IDThe identifier of the user account that makes the application.
LOCALEThe language code of the user.

Rules

  • 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.

On this page