Comments? Feedback?

This wiki does not yet support public comments (a limitation of Google Sites), so we encourage you to post your comments either:

On Twitter by responding to @orbeon.

On our community mailing list: subscribe sending an email to ops-users-subscribe@ow2.org (content of subject/body doesn't matter), you'll get a response with the email to use to send your message to the community mailing list.

Recent site activity

How-to guides‎ > ‎XForms View‎ > ‎

Edit details in a dialog

The problem

You have a table, such as:


You want users to be able to edit this data. You determine that putting form controls inside the table would not use the space in an efficient way, and instead want to enable users to edit this data by clicking on an edit trigger you show on every row which shows a dialog, such as:



When users click on OK, their changes are taken into account, but they are ignored when they click on cancel, or click on the x at top-right of the dialog.

The solution

Imagine you have a main instance with the data shown in the table:

<xforms:instance id="planets">
    <planets>
        <planet>
            <name>Mercury</name>
            <description>Mercury (0.4 AU) is the closest planet...<description>
        </planet>
        <planet>
            <name>Venus</name>
            <description>Venus (0.7 AU) is close in size to Earth...</description>
        </planet>
    </planets>
</xforms:instance>

Because you want users to be able to close the dialog without saving changes:
  1. You need to copy the information corresponding to the row being editing into another instance before opening the dialog.
  2. The controls in the dialog will point to that other instance.
  3. When users close the dialog with OK (instead of cancel), you copy back the changes to the main instance.
This example stores the planet being edited within instance('ui')/edited-planet. The ui instance is declared as:

<xforms:instance id="ui">
    <ui>
        <edited-planet/>
    </ui>
</xforms:instance>

The edit trigger that does the copying and opens the dialog is declared as:

<xforms:trigger appearance="minimal">
    <xforms:label>Edit</xforms:label>
    <xforms:action ev:event="DOMActivate">
        <xxforms:variable name="current-planet" select="."/>
        <xforms:insert context="instance('ui')/edited-planet"
            origin="instance('planets')/planet[name = $current-planet/name]"/>
        <xxforms:show dialog="edit-planet-dialog"/>
    </xforms:action>
</xforms:trigger>

The xxforms:show action refers to a dialog id (edit-planet-dialog), which looks like:

<xxforms:dialog id="edit-planet-dialog">
    <xforms:label>Edit Planet</xforms:label>
    <xforms:group ref="instance('ui')/edited-planet/planet">
        ...
        <xforms:output value="name">
            <xforms:label>Planet</xforms:label>
        </xforms:output>
        <xforms:textarea ref="description" class="edit-planet-textarea">
            <xforms:label>Description</xforms:label>
        </xforms:textarea>
        ...
    </xforms:group>
</xxforms:dialog>

The xforms:group in the dialog points to instance('ui')/edited-planet/planet, which is the planet that was copied from the main instance when the dialog was opened. When the OK button is clicked, you want to copy the data back to the main instance. In this case, only description is being edited, so an xforms:setvalue copying the description is enough:

<xforms:trigger>
    <xforms:label>OK</xforms:label>
    <xforms:setvalue ev:event="DOMActivate"
        ref="instance('planets')/planet[name = context()/name]/description"
        value="context()/description"/>
</xforms:trigger>

You also want to close the dialog when OK is pressed. But since you want to do this for both the OK and cancel triggers, instead of adding an event handler on both triggers, you can exploit event bubbling and place only one handler on an ancestor of both triggers, here directly under the xxforms:dialog:

<xxforms:dialog id="edit-planet-dialog">
    <xforms:label>Edit Planet</xforms:label>
    <xxforms:hide ev:event="DOMActivate" dialog="edit-planet-dialog"/>
    ...

Also when the dialog closes, you want to remove the planet you copied in instance('ui')/edited-planet. You want to do this when the dialog is closed after users press OK or cancel, but also when they click on the x at the top-right of the dialog. You can do this by reacting to the xxforms-dialog-close event which is dispatched to the dialog in all 3 cases:

<xxforms:dialog id="edit-planet-dialog">
    <xforms:label>Edit Planet</xforms:label>
    <xforms:delete ev:event="xxforms-dialog-close" nodeset="instance('ui')/edited-planet/planet"/>
    ...

Run it and get the source