Conditional Presence versus Conditional Visibility

InfoPath supports a feature called Conditional Formatting which allows among other things to show or hide sections of the form based on some condition.

 

However, the underlying XML data still stays there even though it is not visible in the view. What if one wants to remove the XML data altogether? It is easy to achieve this by writing a little bit of code.

 

First of all, a trick: an optional leaf field can be wrapped in an Optional Section without adding any additional nodes in the Data Source. Suppose that your data source looks like that:

 

      myFields

              field1

 

Instead of dragging field1 into the view (which will produce a Text Box, assuming its datatype is a string), right-click on it, select More… and pick Optional Section with Controls.

 

Now the Text Box is wrapped in an Optional Section and you can remove or insert it as desired.

 

At this time, suppose that you want field1 appear conditionally based on a state of a Check Box bound to some node (let’s call it field2). Attach an “OnAfterChange” event to it with the following code:

 

function msoxd_my_field2::OnAfterChange(eventObj)

{

      if (eventObj.IsUndoRedo || eventObj.Operation != "Insert")

      {

            return;

      }

      if (eventObj.NewValue == "true")

      {

            XDocument.View.ExecuteAction("xOptional::insert", "field1_1");

      }

      else

      {

      XDocument.View.SelectNodes(XDocument.DOM.selectSingleNode("/my:myFields/my:field1"));

            XDocument.View.ExecuteAction("xOptional::remove", "field1_1");

      }

}

 

Here, we use the xOptional::insert command to insert field1 (and hence the Optional Section) when the Check Box is checked, and xOptional::remove to remove it when the Check Box is unchecked.

 

A few comments on the code above:

  • The “field1_1” string is the xmlToEdit name associated with the section. To find out what this name is for your section, look at the “Advanced” tab of the Optional Section properties.
  •  When executing actions, InfoPath is using the current XML context to determine how to perform the action. Clicking on the checkbox moves the XML context to field2 in our example. While InfoPath can still handle the insertion properly, it cannot figure out what section to delete. In order for xOptional::remove to succeed, we use SelectNodes() method on the view to set the xml context to the section we are trying to remove.
  • Finally, to prevent the user from inserting or deleting the Optional Section by other means than using the Check Box, bring up the properties of the Optional Section, click “Customize Commands” and uncheck everything under “Insert” and “Remove” actions. Also uncheck the “Show insert button and hint text”.

P.S. The conditional presence technique is especially useful in scenarios where the schema contains optional elements that are not allowed to be blank (which could be a desirable design in some scenarios where the XML-consuming backend cannot handle xsi:nils).

P.P.S. The technique of calling View.SelectNodes() can solve the ExecuteAction() focus/context problem. The ExecuteAction() documentation states that sometimes calling ExecuteAction() from button’s onClick can fail. Calling View.SelectNodes() from onClick shold remedy to this problem.