Add a pop-up message to prompt the CHV to ask further question or give more information or provide health education

Scenario 1: A CHV is asking sensitive questions to HH members on Hepatitis B. In the workflow, I want to alert the CHV to: Be sensitive when asking the next Questions

How we are designing for this: We put a note for the CHV saying, Note: Be sensitive when asking the next Question

New suggestion: Is it possible to pause the workflow at this point and include a message or notification that tells the user that they need to obtain additional information before continuing with the workflow. This could be in the form of a pop-up message or a prompt that appears on the screen. This pop-up message could be prompted by a response to a previous question.
Once the CHV has taken note of the prompt, they can return to the workflow and answer the question about hepatitis B.

Scenario 2: CHVs complain that the MNCH workflow forms are long. Part of the reasons for the long forms is because we have included health education messages and instructions within the forms. We would like to keep the form short and precise.

New suggestion: Can we use the pop-up message containing the Health education messages or the instructions floating on the screen prompting the VHT to read and return back to the workflow questions? This approach allow CHVs to pause the workflow and read information without disrupting the user’s overall experience. It also helps shorten the forms as desired

cc. @Nicole_Orlowski @michael @Ziithe


So, I do not believe there is a built-in way to pop up a message/prompt when filling out a form. However, I have confirmed that it is possible to achieve behavior similar to what you are proposing with a custom extension-lib. Basically the idea is to create a custom extension-lib function that allows for opening an alert from the browser/app.


Create a new extension library with the following code:

const getValue = function(obj) {
  let val;
  if (obj.t === 'arr') {
    val = obj.v && obj.v.length && obj.v[0];
  } else {
    val = obj.v;
  if (!val) {
    return '';
  return val.textContent;

module.exports = function(first) {
  const message = getValue(first);
  return first;

Then you can use the extension-lib function in a form like this:

type name label::en relevant appearance calculation
begin group page NO_LABEL field-list
string message Enter alert message
trigger show Show Alert?
calculate alert ${show} = “OK” cht:extension-lib(“alert.js”, …/message)
end group page

This will cause the alert to be opened whenever the alert field becomes relevant. (Also, you could use window.confirm in the extension function instead if you want to record a boolean value of the user’s response to the alert.)

This would work for brief notification messages, but is probably not ideal for long-form documentation. For that it would be nice to have a more sophisticated approach. Several issues have been logged recently that would provide interesting options here:


This is awesome @jkuester … any chance you have a little video of what it looks like :movie_camera: ?

1 Like


Hi @jkuester,

On xlsx forms that has its settings style property set to pages, when implementing the trigger and alert.js via the calculation field, as suggested, it causes the alert dialog to be displayed unexpectedly in the following cases:
On next/previous press.
On clicking an option in a multi_select widget that has an appearance of minimal.

Is there a way to circumvent this?


I should have known this was too good to be true… Unfortunately you are correct. I neglected to test this against a multi-page form. :disappointed: Currently the CHT force-recalculates the expressions when changing pages which is why the alert is triggered by the next/previous buttons. Sadly the options for improving this behavior (without updating code in cht-core) are somewhat limited since Enketo does not support any kind of logic short-circuiting in its XPath evaluations.

  • One option is to only trigger the alerts on the last page of the report (as long as they are not relevant until the last page, they should not be triggered when navigating between pages), However, after they are relevant, they would get triggered if the Previous button is used.
  • Another option is to use some logic in your extension-lib function to control when the alert is displayed. There are probably a number of ways to do this, but one simple thing I tried was:
    • Update the extension-lib function to take a new param:
      module.exports = function(startParam, messageParam){
        const message = getValue(messageParam);
        const start = getValue(startParam);
        if(!global.chtAlertStart || global.chtAlertStart !== start) {
          global.chtAlertStart = start;
        return messageParam;
    • Then in your form, include the start metadata field
    • Finally, pass the value for start when calling the function: cht:extension-lib(“alert.js”, ${start}, ${message})
    • start should be accurate to the millisecond, so it is unlikely to cause collisions even when quickly switching between forms, but should always remain the same value while the current form is being filled out.

Obviously these not not great workarounds, but they are the only ones that I have come up with so far. A proper solution (with broader performance benefits) might require refactoring Openrosa XPath Evaluator to support short-circuiting evaluations so that it does not always evaluate both sides of an expression if it can know that one value will be unnecessary (e.g. when computing a boolean ${A} or ${B}, it would be better to compute ${A} first. Then, if ${A} is true, just skip evaluating ${B} altogether (since its value does not matter)).

Also, the multi_select issue you noted poses a unique challenge to this kind of functionality. Each time you select a new item in a multi_select, it is recorded as a fresh “answer” to the question (and so any expressions that depend on that question value will be re-calculated. In that sense, if your alert is triggered by answering the multi_select then it is expected behavior that it would be triggered for each relevant selection. (That being said, my start workaround should also prevent re-alerts for this case too…)