Triggering Mini-Forms in O3 Forms

Aka: Conditional Form Workflow for Sequenced Component Forms

This Thurs & Fri, @dennis and I are privileged to be working with the @PalladiumKenya O3 engineering team in Nairobi. This is one of the issues we’ve been discussing:

Scenario: Palladium finds there are often multiple sets of forms required for a typical HIV clinician to do, depending on some patient characteristics (e.g. sex, age), some in-form answers (e.g. today’s temperature, LMP), and user roles (e.g. some are done by doctors, some only by nurses, etc).

Currently users manually select which forms to do for a given patient based on this logic. But this means open a form, close a form, open, close, open, close, open, close… which is painful.

These are just a few of the forms that can be triggered:

  • Cervical Cancer Screening
  • ART Adherence
  • Pregnancy Screening: e.g. based on Age >15 or LMP >x days
  • ILI/Flu Screening: e.g. if Temperature >38*C
  • HIV Testing
  • TB Screening

Vision: Each of these “mini-forms” (called component forms in O3 schema) should follow a clinical workflow that gets triggered automatically for the user, during a form workflow, so the outpatient end-user only has to follow the flow of a single form experience.

  • E.g.: Based on appointment types, this is an ANC client who is HIV positive → Show component forms for HIV and ANC things.

Implementation Ideas:

  • Use the form schema to define a workflow, where Component forms would be referenced in the form schema like usual (Referencing Component Forms)
  • Trigger logic for each component form in the form schema, by extending the hideWhenExpression to apply to Component Forms, not just questions. This already covers cases like previous question answers in the current form, sex, and age. So e.g. for the Pregnancy Screening, it might look something like:
    • { “hide”: { “hideWhenExpression”: “sex !== ‘M’” AND “LMP < 6weeks” }}
  • These component forms would ideally also have configuration for if you need them to have their own encounter type to help with subsequent data review (e.g. “Cervical Cancer Screening Encounter”).


  • Feedback? Suggestions?
  • Should we create a showWhenExpression instead? Is this a better user experience than the inverse logic of hideWhen? If so, what’s the lift?
  • What challenges would we run into in order to apply User Roles also?
  • Would extending the applications of hideWhenExpression to Component Forms also help us with extending hideWhen to things like Form Pages or Sections or Answer Options?

CC @samuel34 @dkayiwa @ibacher @frederic.deniger @mseaton @mogoodrich @ddesimone @slubwama


Triggering component forms based on logic is a reasonable approach;

would depend on the specific use case and the desired user experience. If the goal is to show only the relevant component forms and minimize the number of forms displayed to the user, then a hideWhen approach may be more appropriate. On the other hand, if it is important to make it clear to the user which forms are available and why, then a showWhenExpression approach may be more suitable. Ultimately, the decision would need to be based on user feedback and testing.

The lift to implement this would depend on the complexity of the logic involved and the impact on the overall system. It may also require changes to the O3 schema and documentation.

Given, OpenMRS 3.0 OHRI Package is focused on the fundamentals of package development, I may not be so much familiar with OpenMRS database schema and how to query it to retrieve patient information and other relevant data;

However, i have some questions;

  1. How will we handle cases where a patient’s characteristics or in-form answers do not fit neatly into the predefined workflow? Will there be a way to manually select the appropriate forms in these cases?

  2. How will we handle potential errors or conflicts that may arise when triggering multiple component forms simultaneously? For example, what happens if two forms require conflicting information or actions from the clinician?

@drjaqobo something interesting here

Thanks @grace for the post!

This is something we do fairly frequently in the PIH EMR using HTML Form Entry, and so would definitely be a key feature if PIH was going to adopt O3.

One thing HTML Form Entry does really support are “mini-forms”, so we generally have one large form and the hide/show sections based on logic like sex, age, answers to previous questions, program enrollments, etc. We’ve often talked about the need to “mini-forms” in order to make these form components reusable. So behind able to include and hide/show mini-forms would be a nice improvement for us.

What’s the different to the the end user between showWhenExpression and hideWhenExpression? It’s the only difference whether a logic expression that evaluates to true shows or hides the form? I would think it would straightforward to create a hideWhen that really just needs to do the inverse of showWhen, and then the form developer could use whatever is most convenient to them. Or am I missing something?

Finally, regarding own encounter type… the main thing would actually be to make sure that mini-forms could all be grouped under the same encounter (which sounds like a the presumed default behavior if I’m understanding correctly).

Thanks! Mark

@fanderson @ball @mseaton @ddesimone

Assume that “hidden” means “not shown” and “shown” means “not hidden”, then I suppose this is just a matter of which version form authors find easier to reason about.

I’ve got a few cautions here those:

  • Supporting both showWhen and hideWhen will be more challenging than supporting just one or the other
  • Since we’re already using hideWhen, adding showWhen would either mean supporting both or basically breaking any form that’s been developed using hideWhen

I don’t like the idea of using a form schema to define a workflow. I think that’s an anti-pattern that should be discouraged. Forms that embed workflow-specific logic become, by their very nature, program and even clinic specific, meaning they can’t be effectively shared across implementations.

Embedding workflow-related logic in forms also makes it hard to maintain a GUI form editor because the form being edited moves further and further away from the relative simplicity that makes it easy enough to maintain a working GUI form-based editor.

I think having component forms is obviously fine and adding some hideWhen support to component forms is a great idea, but we should not be trying to use this to define workflows. I do agree that we need to make things easier for users to move between forms and I’m very happy to discuss how we can implement these sort of customisable workflows. I just don’t think they belong inside individual forms. Perhaps we add some hooks that implementations can override to, e.g., move to the “next” form after a previous form has been completed (and we could feed these hooks relevant patient details, user details, and even values from the previous encounter).

This is the strongest argument I can think of for why these “component forms” should just be separate forms.

First, supporting this will require reworking the form engine itself, the form app, and the fast-data-entry stuff, as well as the offline stuff, all of which are designed premised on the idea that each form operates on a single encounter.

Second, supporting viewing the entered data in forms already will require us to have each “form component” as a separate, self-contained form.

A few comments here:

  • Roles should always be groupings of permissions, and those permissions should be what we use to control access to resources. Roles themselves should not be treated as security privileges (e.g., instead of having a rule that says role === 'Doctor', we should have a rule like privilege === 'Assess ART Adherence' and assign that privilege to the Doctor role. This is because it allows us to be more agile, e.g., when the clinic decides next week that doctors are too busy to do all the ART adherence assessments and they want the nurses to do that, we just need to add a privilege to the Nurse role.
  • In general, I don’t love driving what parts of a form might be filled out based on who a user is. I can see that when viewing a form, it might be critical to hide sensitive sections for some users, but those users should not be able to fill out the same form. Hiding or showing sections of a form based on facts about the patient seems perfectly fine, i.e., if a form skips questions related to pregnancy for a patient who cannot be pregnant, I can’t see it raising any questions. However, if I’m browsing a form and there’s a required section that’s completely blank because the form was originally filled out by someone with fewer privileges than me, that seems like bad UX that’s likely to lead users to mistrust the completeness of that particular form and maybe the EHR as a whole.

I don’t think it necessarily helps us one way or the other; adding support for hideWhen expressions to pages and sections is a great idea and we should implement it immediately. I’m much more ambivalent about using them to hide answer options, but I think that warrants a whole different discussion…

I agree with a lot of @ibacher and @mogoodrich comments. In lieu of a long-winded post, I’ll just say that I’d love to discuss this more in an upcoming forum.

There is a lot to learn from what has been developed in htmlformentry around this, and the good, the bad, and the ugly from that. Clearly there is a need for us to capture observations conditionally based on either not-yet-saved encounter data, or previously saved patient / encounter data. But we should also take care to limit the amount of custom code that is embedded in forms themselves, or in placing too much undue importance on “Forms”, in favor of looking at how form components can fit into an overall clinical workflow.

It isn’t totally the same conversation, but I’d like to ensure that we are considering some of the direction that we are proposing with the encounter context in mind. The idea being that we want to support frontend components that can contribute to an encounter outside of the form engine itself but which still fit into an intuitive workflow for the user/clinician. Some examples that feature prominently at PIH are recording lab and drug orders, recording program enrollments and state transitions, and entering vaccination history.

I’d be curious to explore a model where the form engine doesn’t actually take responsibility over the entire encounter, but simply allows for “component forms” to be used to enter and render observations collected in a broader encounter context workflow.

I think I tend to agree with this, to clarify, we are saying the form engine should support this:

  • On the NCD Form, include the Women’ Health form component if the patient is female

but not:

  • On the NCD Form, define a workflow that says open the Women’s Health form after the NCD Form is completed if the patient is female

I’m probably missing something here about why this is complicated, but we can discuss… :slight_smile:

Agreed, we should explore this!

Take care, Mark

Count me in if you need further examples. I have plenty. They include the following:

  • For all females, ask about pregnancy
  • If female, include gestational diabetes or hypertension on NCD form
  • if < 2 years old, include infant birth questions, feeding, and supplements
  • Based on age and gender, show pregnancy tests, PAP smear, HIV PCR,
  • limit intake questions to one time (HIV, NCD)

These are very good observations. We stand to benefit from the ‘mini-forms’ in many ways including but not limited to:

  • Minimal redundancies across different forms
  • Ability to group related questions in a simple mini-form
  • Greater user experience and data completeness through enforced work
  • A more patient-centric approach to care provision
  • Faster design and development of new forms, etc

Even as we continue with our discussions here, I would request if @grace can help schedule a call for immediate next steps. We really need this concluded for our current transition to o3.

1 Like