Rendering Fields Conditionally
Angular Form Engine scope. This page documents conditional rendering in
@openmrs/ngx-formentry. Equivalent schema fields may behave differently in the React Form Engine. See About this documentation.
You can render Form fields conditionally by defining a hideWhenExpression inside the hide property of your question definitions.
A hideWhenExpression is a JavaScript expression that returns a boolean value (true or false). Logical operators (opens in a new tab) are used to construct these expressions. Additionally, you can incorporate injected data sources and expression helper functions into your expression definitions.
To write a hideWhenExpression, include a code block like this within the questions array of your
question definition:
{
"hide": {
"hideWhenExpression": "isEmpty(onArt) || onArt !== 'a899b35c-1350-11df-a1f1-0026b9348838'"
}
}In the example above, the logic instructs the Angular Form Engine to hide (not render) the question with the onArt id if the value of its backing concept does not match the supplied value.
You can only add a hide property to questions, including obsGroup
questions. Sections and pages don't support it. However, the engine stops
rendering a section once every question in it is hidden, including the section
header. To hide a set of questions together, put them in their own section and
give each question the same hideWhenExpression.
Don't use the word return anywhere in an expression, and check that every id
it references exists in the form. Either mistake leaves the question visible
without an error. See How expressions are
evaluated.
What happens to a hidden question
When a question gets hidden, the engine clears its value and disables it. Anything the user entered in it is lost, even if the question becomes visible again.
Using the field and value shorthand
Instead of an expression, you can give hide a field and a list of values. The question is hidden unless the question with the id in field has one of the listed values:
{
"hide": {
"field": "onArt",
"value": ["a899b35c-1350-11df-a1f1-0026b9348838"]
}
}This is the same as "hideWhenExpression": "!arrayContains(['a899b35c-1350-11df-a1f1-0026b9348838'], onArt)". value must be an array. If it isn't, the question never hides.
More examples
1. Using the isEmpty helper
{
"hide": {
"hideWhenExpression": "isEmpty(screenedForHepatitisB) || screenedForHepatitisB == '1066AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'"
}
}In this example, the question being validated gets hidden if the question with the id screenedForHepatitisB is empty or if its value is the answer backed by the concept ID 1066AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA. Most often, if your hideWhenExpression is not working, it's likely because you did not use the isEmpty helper as shown above.
2. Using the sex model from a patient data source
{
"hide": {
"hideWhenExpression": "sex !== 'F'"
}
}In this example, the question being validated gets hidden if the patient's sex is F. For this expression to work, you would need to plug in a patient object that exposes a gender property mapped to either F (for female) or M (for male).
Read more about this in the data sources guide.
3. Using the age model from a patient data source
{
"hide": {
"hideWhenExpression": "age >= 18"
}
}In this example, the question being validated gets hidden if the patient's age is greater than or equal to 18. For this expression to work, you would need to plug in a patient object that exposes an age value. Read more about this in the data sources guide.
Hiding fields based on a previous observation
In O3, you can hide questions based on a value recorded in an earlier encounter. For example, a single form for all patients can show HIV care questions only to patients whose last recorded HIV status is positive, without asking for the HIV status during the visit.
This uses useMostRecentValue. When the form loads, O3's form entry app fetches the patient's most recent observation for the concept of every question marked with useMostRecentValue, from any encounter. It registers the results as the rawPrevObs data source, which hide expressions can read by name. rawPrevObs has the following shape:
{
"obs": [
{
"concept": { "uuid": "159576AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" },
"value": { "uuid": "703AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" }
}
]
}Coded values come through as { "uuid": "..." }, and numeric and text values come through as plain values. Observations with other value types, such as dates, are left out.
First, add a hidden helper question for the concept you want to look up. Its only job is to get the concept fetched. Because it's always hidden, it never gets a value and doesn't save an observation.
{
"label": "Last recorded HIV status",
"id": "lastHivStatus",
"type": "obs",
"questionOptions": {
"rendering": "select",
"concept": "159576AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"useMostRecentValue": true,
"answers": [
{
"concept": "703AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"label": "Positive"
},
{
"concept": "664AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"label": "Negative"
},
{
"concept": "1067AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA",
"label": "Unknown"
}
]
},
"hide": {
"hideWhenExpression": "true"
}
}Then add a hideWhenExpression like this one to each question you want to show only to HIV positive patients:
{
"hide": {
"hideWhenExpression": "!(rawPrevObs && rawPrevObs.obs.some((o) => o.concept.uuid === '159576AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' && o.value && o.value.uuid === '703AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'))"
}
}Keep the following in mind:
- Keep the
rawPrevObs &&check. When the patient has no matching observations,rawPrevObsisundefined. - Put the helper question at the top level of a section. The form entry app doesn't look for
useMostRecentValueon questions nested in anobsGroupunless the group has the flag too. - Use an arrow function, as shown above. An expression that contains the word
returnnever hides the question. - Only the most recent value is considered. If the status changes during the current visit, the expression won't pick it up unless it also checks the relevant question on the form.
- If you put the questions in their own section, the whole section disappears when all of them are hidden.