XForms/Referencing Items
Motivation
editYou wish to associate a form with a set of items. Once an item is referenced it should not be referenced again.
For example if you have a form that edits tasks you may want to associate a specific task with one or more projects. Once a project is associated with a task you want to remove it from the candidate list of projects it can be associated with.
The way to visualize this is to imagine a set divided into two distinct subsets: selected and un-selected items. As an item moves from the un-selected item set to the selected item set it must first be added to the new set and then deleted from the old set.
Method
editThis example uses a combination of the repeat and the switch/case. The currently referenced items are listed in a repeat loop. A button called "Add Reference" uses the toggle function to reveal a list of unselected items. As you select an item it is added to the selected list.
Sample Program
edit<html
xmlns="http://www.w3.org/1999/xhtml"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xf="http://www.w3.org/2002/xforms">
<head>
<title>Form References</title>
<style type="text/css">
@namespace xf url("http://www.w3.org/2002/xforms");
body {font-family:Helvetica, sans-serif}
</style>
<xf:model>
<xf:instance xmlns="" id="unreferenced-items">
<data>
<reference>
<reference-id>1</reference-id>
<reference-name>Reference 1</reference-name>
</reference>
<reference>
<reference-id>2</reference-id>
<reference-name>Reference 2</reference-name>
</reference>
<reference>
<reference-id>3</reference-id>
<reference-name>Reference 3</reference-name>
</reference>
<reference>
<reference-id>7</reference-id>
<reference-name>Reference 7</reference-name>
</reference>
<reference>
<reference-id>8</reference-id>
<reference-name>Reference 8</reference-name>
</reference>
<reference>
<reference-id>9</reference-id>
<reference-name>Reference 9</reference-name>
</reference>
</data>
</xf:instance>
<xf:instance xmlns="" id="referenced-items">
<data>
<reference>
<reference-id>4</reference-id>
<reference-name>Reference 4</reference-name>
</reference>
<reference>
<reference-id>5</reference-id>
<reference-name>Reference 5</reference-name>
</reference>
<reference>
<reference-id>6</reference-id>
<reference-name>Reference 6</reference-name>
</reference>
</data>
</xf:instance>
</xf:model>
</head>
<body>
<h3>Demonstration of Referencing External Items in an XForms Application</h3>
<xf:group class="group-label">
<xf:label>Currently Referenced Items:</xf:label>
<xf:repeat nodeset="instance('referenced-items')/reference">
<xf:output ref="reference-name"/>
</xf:repeat>
<xf:switch>
<xf:case id="init">
<xf:trigger>
<xf:label>Add Reference</xf:label>
<xf:toggle case="add-reference" ev:event="DOMActivate"/>
</xf:trigger>
<xf:input ref="my-element">
<xf:label>Reference Name: </xf:label>
</xf:input>
</xf:case>
<xf:case id="add-reference">
<xf:label>Un-Referenced Items:</xf:label>
<xf:repeat nodeset="instance('unreferenced-items')/reference" id="unreferenced-item-repeat">
<xf:trigger>
<xf:label><xf:output ref="reference-name"/></xf:label>
<xf:action ev:event="DOMActivate">
<xf:insert nodeset="instance('referenced-items')/reference" at="last()" position="after"/>
<xf:setvalue
ref="instance('referenced-items')/reference[last()]/reference-name"
value=" instance('unreferenced-items')/reference[index('unreferenced-item-repeat')]/reference-name "/>
<xf:setvalue
ref="instance('referenced-items')/reference[last()]/reference-id"
value=" instance('unreferenced-items')/reference[index('unreferenced-item-repeat')]/reference-id "/>
<xf:delete nodeset="instance('unreferenced-items')/reference" at="index('unreferenced-item-repeat')"/>
</xf:action>
</xf:trigger>
</xf:repeat>
</xf:case>
</xf:switch>
</xf:group>
</body>
</html>
Discussion
editThe unreferenced items are not displayed unless the user selects the "Add Reference" trigger. When the user selects the Add Reference trigger the list of currently unreferenced items is displayed.
When the user selects the trigger of an unreferenced item a new item is added to the end of the referenced items list and removed from the unreferenced items list.
This pattern can be used in many examples. For example when you create a custom report you are presented with a list of columns to display. These columns are either referenced in the display list or not referenced.
The user interface sometimes shows these lists side-by-side. This can be accomplished by adding a class to each of the groups and using CSS to display the lists side-by-side.
The one problem with this example is the inability to place the items in the correct order after they are moved to a new list. Hopefully a future version of XForms will support this.