Projects‎ > ‎Core‎ > ‎

Dynamic XForms

STATUS: This is implemented in Orbeon Forms 4.0 for use by Form Builder.

Motivation

As of Orbeon Forms 3.9, Form Builder interprets the form it is editing, instead of running them "live". This has some benefits, but also limitations, in particular:
  • each construct (fr:section, fr:grid, and all controls) must be interpreted in a custom way
  • XBL can only be used if it is known by FB in advance
  • same for repeats, grids, etc.
  • need to use "switch" between controls, which costs resources and increase the size of the client DOM
The idea of dynamic XForms is the ability to tell the XForms engine to run, live, a sub-form, that can be dynamically modified by the builder (or other XForms, but Form Builder is the main use case).

Form author interface

Usage:

<xxf:dynamic ref="instance('my-sub-form')"/>

This creates a shadow XForms document sub-form or "part", which lives in a shadow (inner) scope.

In the example above, mutations to the my-sub-form instance are reflected in the part:
  • mutations to inline instances
  • mutations to the control tree
  • adding, removing and updating model content

Implementation notes

Where it fits

  • XFormsStaticState is split into PartAnalysis and interfaces
  • a page has a top-level part, equivalent to the earlier XFormsStaticState
    • cacheable/sharable/immutable
  • a page can have sub-parts
    • not cacheable, at least not alongside the top-level part
    • ⇒ sub-parts cannot be referenced by the top-level part
The following drawing shows how two Form Builder documents have their own sub-parts (for the forms being edited, which are different), and a common single part (for Form Builder itself, which can be shared).



<xxf:dynamic>

Implementation:
  • XXFormsDynamicControl
  • XXFormsDynamicHandler
Upon mutations:
  • "static" information is updated (parts)
  • "dynamic information is updated
  • markup for client is generated as needed in Ajax responses
    • incremental updates if no structural change to control tree
    • full updates if structural change to control tree

Optimizing incremental updates

In general, the source of the sub-form is not modified instantly, but through insert/delete/setvalue ⇒ incremental updates are possible.
  • updates to instances back and forth [DONE]
  • updates to binds [DONE]
  • updates to top-level XBL bindings [DONE]

Instance write-through

  • When the content of inline instances in the source of the outer form is mutated, the content of the live instances of the sub-form is updated accordingly.
  • When the content of live instances in the sub-form is mutated, the source of the inline instance in the outer form is updated accordingly.
This is done with event listeners:
  • xxforms-value-changed
  • xforms-insert
  • xforms-delete

Use by Form Builder

  • form edited by Form Builder is a sub-form referenced by <xf:dynamic/>
  • editor edits by modifying that instance
  • FB communicates to the sub-form
    • edit-ref / xxf:instance() on section, grid
    • selected="true" on grid cells
  • who does what?
    • fb:form-editor
      • global object for editor actions
        • fb-delete-control
        • dialog-control-details
        • MORE
        • NOTE: poor man's way of having a global set of functions!
    • some actions are done from the outside by the builder itself
      • insert control
    • some actions are done from the inside by editable components, e.g.:
      • fr:grid handles
        • add rows/cols
        • remove control from cell
        • rowspan
        • places cell editor in non-empty cells [maybe only in selected cells? -> no because must work on hover!]
      • fr:control-editor handles [NO LONGER]
        • LHHA
        • control properties + validation
        • itemset
    • fr:section/grid/control-editor, etc.
      • are exposed $fb-resources
Comments