Multiple Top Level Subforms

I’m willing to bet that all the XFA form definitions you’ve looked at all have one top level subform.  Not surprising, because that’s what Designer
allows you to author.  But according to the XFA specification, there can be any number of top-level subforms below the <template> root.

Today I’ll briefly describe the processing rules for top-level subforms, provide a simple example where you might find them useful, and give you a couple of macros to make these easier to work with in Designer.

The Processing Rules

The rules are simple:

  • When there are multiple top-level subforms, only one is rendered.
  • We choose which subform to render based on which one best matches the data.  i.e. the template behaves like a choice subformSet: <subformSet relation="choice">. 
  • If no data is supplied, we render the first subform below the <template> element

A Sample

Suppose I want different variations of my form for printing and for interactive.  I construct my template so that it has top level subforms for both print and interactive.  Since the binding is all "by name", the form will render according to the name of the top level node in the data.  Try previewing the sample with these data files: interactive.xml, print.xml — or import these data files in Acrobat, and you’ll see the form change according to the data provided.  However, controlling print behavior with different data files is more applicable on the server than on the client. 

In order to force the form to use the print subform when printing from Acrobat/Reader, I added a pre-print event to the interactive root subform.  The script renames the top level node in the data, and forces a remerge.  This will cause the print operation to use the print subform.

interactive::prePrint – (JavaScript, client)
xfa.record.name = "print";
xfa.form.remerge();

Then to restore to the interactive view, I added a postPrint event to the print subform:

print::postPrint – (JavaScript, client)
xfa.record.name = "interactive";
xfa.form.remerge();

Design Experience

I’ve already hinted that Designer doesn’t really support multiple top-level subforms. But with a couple of handy macros, we can get by.

First problem is that there’s no easy way to create a new top level subform.  Here’s a macro to proide that functionality.  You’ll notice when you run the macro that there’s a problem.  The changes made by the macro don’t show up in the hierarchy.  This is a bug that will be fixed next release.  Meanwhile, closing and re-opening the form will workaround the issue.  Note that the macro to add the new top level subform also inserts a default master page (<pageSet>). Designer and the XFA runtime are generally very unhappy if they don’t have a set of master pages to work with.

Next problem is to figure out how to edit the new top level subform in Designer.  Here’s a macro to solve that problem. Since Designer always renders the first subform, this macro re-orders the top-level subforms so that you get a different top-level subform. Specifically, the macro re-orders the first subform to be last.  Just make sure that when you save the form that your preferred default subform is first in order.

Now, for the specific example of print and interactive variations, I could have implemented the solution in a number of different ways.  e.g. with a choice subformSet or with optional subforms at the second level in the hierarchy.  But the point was to bring to light some functionality that you might not otherwise been aware of.