XForms/Moving Items Between Lists

Motivation edit

You have two lists and you would like to move selected items between the lists. This is typically known as a column chooser.

Method edit

The user interface will have two lists, one on the right and one on the left. Between the lists we will see two buttons; Move Left and Move Right. The user can check any number of items on the left list and press the Move Right button to move these items to the right list. The user can also add any number of items on the right list and then by pushing the Move Left button, these items would be moved to the left list.

Note that a "move" is technically two separate operations, a copy followed by a delete. But the user does not see these separate steps.

Sample Screen Image edit

 
Screen Image of Moving Items Between Lists

Link to Working Form edit

Link to Working Form

Sample List Instances edit

  <left-list>
    <item>Item One</item>
    <item>Item Two</item>
    <item>Item Three</item>
    <item>Item Four</item>
    <item>Item Five</item>
  </left-list>
  <right-list>
    <item>Item Six</item>
    <item>Item Seven</item>
    <item>Item Eight</item>
    <item>Item Nine</item>
    <item>Item Ten</item>
  </right-list>

Sample XForms edit

The following form has three columns. One for the left list of items, one for the middle column of move buttons and one for the right list of items.

The Move buttons have two actions.

  1. insert a new item in the list by doing a copy of the selected item to the opposite list
  2. delete the selected item
<div class="left span-3">
   <h3>Left</h3>
   <xf:repeat nodeset="instance('save-data')/left-list/item" id="left-repeat">
    <xf:output ref="."/>
   </xf:repeat>
   
   <xf:output value="index('left-repeat')">
    <xf:label>Left Index: </xf:label>
   </xf:output>
</div>


<div class="middle span-3">
   <xf:trigger>
     <xf:label>Move Right</xf:label>
     <xf:action ev:event="DOMActivate">
      <xf:insert nodeset="instance('save-data')/right-list/item" 
            origin="instance('save-data')/left-list/item[index('left-repeat')]" 
            at="last()" position="after" />
      <xf:delete nodeset="instance('save-data')/left-list/item[index('left-repeat')]" />
      
     </xf:action>
   </xf:trigger>
   <xf:trigger>
     <xf:label>Move Left</xf:label>
     <xf:action ev:event="DOMActivate">
      <xf:insert nodeset="instance('save-data')/left-list/item" 
            origin="instance('save-data')/right-list/item[index('right-repeat')]" 
            at="last()" position="after" />
      <xf:delete nodeset="instance('save-data')/right-list/item[index('right-repeat')]" />
      </xf:action>
   </xf:trigger>
</div>

<div class="right span-3">
   <h3>Right</h3>
   <xf:repeat nodeset="instance('save-data')/right-list/item" id="right-repeat">
    <xf:output ref="."/>
   </xf:repeat>
   
   <xf:output value="index('right-repeat')">
    <xf:label>Right Index: </xf:label>
   </xf:output>
</div>

Sample CSS edit

The "span-3" tags use the standard blueprint framework to span three columns in a 24 column page.

The other CSS tags are used below with XSLTForms. Note that the selected item on the list is white.

    @namespace xf url("http://www.w3.org/2002/xforms");
    .left, .middle, .right {border: solid gray 1px; background-color: lavender;}
    .xforms-repeat-item-selected {color: blue; background-color: white;}

Discussion edit

The list on the right side could also be re-orderable. This is typically a use-case for a report-writing tools that allows a user to select columns from a list for a report.