Bahmni Form Builder - Form Conditions & Skip Logic

Our observation forms provide a way to enable/disable some fields in a form based on implementation specific form conditions configuration. The wiki page for configuring it is available here.

This post talks about handling the form conditions using the new form definition approach. As of today, the form conditions are managed in a separate javascript file in the respective implementation config repositories (here & here). Basically, the form conditions talks about various rules. The following are some different kinds of rules that we have seen till date.

Rule Type 1: When a single select radio option for the question “Baseline, Employment within the past year” is selected as “Other”, then enable a form field “Baseline, Other employment”. Otherwise disable it. Rule Type 2: When “Baseline, WHO registration group” is selected as either “Relapse”, “Treatment after loss to followup”, “Treatment After Failure to Drugs”, then enable a text box “Category IV tuberculosis classification”. Rule Type 3: For the question “Did patient start treatment”, if there is no answer, disable certain fields, if the answer is true - enable & disable certain fields, if the answer is false - then enable & disable certain fields

We want the form conditions to be part of the form definitions.

The advantages are

  1. The form is complete by itself and might not depend on any extra files except for the i18n. This will be helpful with our vision of form banks. They can operate independently.
  2. The form conditions can be simple. Today, they are very verbose. With the availability of control ids, it’s easy to identify. Also, today we are limited to using Concept Names as the keys. If a form uses 1 concept at multiple places, then these form conditions will NOT work.
  3. One form can define conditions specific to its own control and can be managed separately unlike one huge file maintaining skip logic of all the forms.

The disadvantage are

  1. Form size can grow
  2. One time migration effort is involved for our existing implementations
  3. Some standard evaluators of form conditions is provided out of the box, but we need to provide a flexibility to add more by Implementers (more on this later).

A sample form defn with form conditions might look something like this. Line 71 is function defn & Line 45 is function usage.

The parameter that is sent to the function can include some contextual information like patientContext, visitContext, formContext (contains metadata), the value that is being selected for the current control etc. This information is useful for writing effective form conditions.

We are yet to spike out and see how things work. But wanted to get some preliminary inputs from the community. Thank you.

Another way to accomplish the same would be to allow expressions in the control properties:

“properties”: { “mandatory”: false, … “enabled” : “javascript expression” “visible” : “javascript expression” },

More things nice to have:

  • reusable complex controls
  • inheritance/composition of forms
  • mandatory property conditional
  • style attributes conditional
  • layouts

Thanks @lluismf

We are also internally debating on having enabled/disabled properties with some DSL instead of functions. But having functions can provide more flexibility in terms of what an implementer can do. It might become very complex to write the expressions and sometimes they might be handicapped. What do you think?

We are relying on ReactJS for componentization. So, composing multiple controls to make a composite control will be easy. Also, we support composition for Concept Set out-of-the-box (we are developing as we speak). i.e. provide a Concept Set as an input and the form gets constructed with various controls in the concept set. The controls can be laid out (or dragged) to the desired position by the implementer.

Thanks for the suggestion. We will look into “nice to have” you mentioned.

@bharatak regarding enabled/disabled properties with some DSL instead of functions, do you see any disadvantages of providing both?

Sure @dkayiwa. Supporting both might be a good idea. Just need to finalize one for the MVP :slight_smile:

I think that with a DSL the expressions could be simpler. But of course this DSL should be interpreted or transpiled therefore more complex to implement. Obviously with pure JS you can do whatever you want, but is harder for implementers specially if they’re not programmers.

@bharatak, I would imagine that in the long run we will need to support both (a) arbitrary JS functions, and (b) shortcut/DSL for the 80% use cases.

The “enabled” and “visible” expression approach that Lluis mentions is a pattern I’ve seen in quite a few places, and I would think it ties in well to the reactive approach we’re taking (i.e. we know when the form model changes).

In HTML Form Entry module we started by supporting arbitrary javascript, and later added a simpler “when-then” construct for a common use case.

I would lean towards doing the same in the Bahmni form designer: support JS first, and then add the shortcut/DSL version later when we have the time and understanding of use cases to be sure we get the DSL right.