XForms Repeat Element

Introduction

A repeat element contains markup and is itself bound to a nodeset in an instance document (see the spec). For each node in the nodeset, the contents of the repeat element will be displayed in the form. That node will serve as the context node for any relative xpath expressions in that set of repeated markup.

Attributes

  • UI Common
    • appearance - the value of this attribute gives a hint to the XForms processor as to which type of widget(s) to use to represent this control.
  • Node Set Binding
  • Special
    • startindex - optional 1-based initial value of the repeat index. The default value is 1.
    • number - isn't supported

Type restrictions

The repeat element can be bound to a nodeset.

Representations

The repeat element doesn't have a visual representation. However, it can influence the layout of generated controls depending on its appearance attribute.

default layout

Each generated control set is placed vertically.

compact layout

Each generated control set is placed horizontally. Occurs when the repeat element's appearance attribute has a value of compact.

Behaviour

Focusing a generated control may change the current index of the containing repeat element. The index is equal to the index of the control set that the focused control belongs to.

Actions

You can use XForms Action Module elements to modify the nodeset that the repeat element is bound to. The most useful actions for altering the contents of a repeat are the insert (see the spec), delete (see the spec) and setindex (see the spec) elements.

Example

<model>
  <instance>
    <my:lines>
      <my:line name="a">
        <my:price>3.00</my:price>
      </my:line>
      <my:line name="b">
        <my:price>32.25</my:price>
      </my:line>
    </my:lines>
  </instance>
</model>

<repeat id="lineset" nodeset="/my:lines/my:line">
  <input ref="my:price">
    <label>Line Item</label>
  </input>
  <input ref="@name">
    <label>Name</label>
  </input>
</repeat>

<trigger>
  <label>Insert a new item after the current one</label>
  <action ev:event="DOMActivate">
    <insert nodeset="/my:lines/my:line" at="index('lineset')"
      position="after"/>
    <setvalue ref="/my:lines/my:line[index('lineset')]/@name"/>
    <setvalue ref="/my:lines/my:line[index('lineset')]/price">0.00</setvalue>
  </action>
</trigger>

<trigger>
  <label>remove current item</label>
  <delete ev:event="DOMActivate" nodeset="/my:lines/my:line"
                 at="index('lineset')"/>
</trigger>

Attribute based repeat

When using XForms within host languages like XHTML, it is often necessary to create repeating structures within constructs such as html:table. Thus, one might wish to use element repeat within a table to create the rows of a table, where each row of the table binds to a distinct member of a homogeneous collection. Since html:table doesn't (and probably never will) allow xforms:repeat elements as children, another syntax is needed.

To accommodate this, XForms 1.0 defines an alternative syntax that is functionally equivalent to the repeat element, using the following attributes:

  • repeat-model
  • repeat-bind
  • repeat-nodeset
  • repeat-startindex
  • repeat-number

Additionally, when using XForms Action setindex, its repeat attribute (which contains an IDREF) can point to any element carrying these repeat attributes. Similarly, the index function can be used with the repeating structures created via these repeat-attributes. The id of the element that contains the repeat attributes can be used as the argument to index.

Note, we don't fully support attribute-based repeats. There are a number of errors that may occur, especially when these attributes are used with html:table. Be sure to test your form carefully.

Example
<xforms:model id="i_model">
  <xforms:instance xmlns="">
    <data xmlns:html="http://www.w3.org/1999/xhtml" xmlns="">
      <val id="1">
        <nest>Nest 1.1</nest>
        <nest>Nest 1.2</nest>
      </val>
      <val id="2">
        <nest>Nest 2.1</nest>
        <nest>Nest 2.2</nest>
      </val>
    </data>
  </xforms:instance>
</xforms:model>

<div xforms:repeat-nodeset="val">
  This is the inline content, just text. Here comes the output:
  <br/>
  <xf:output ref="@id"><xf:label>Output: </xf:label></xf:output>
  <div xf:repeat-nodeset="nest"><xf:output ref="."><xf:label>Nested output: </xf:label></xf:output></div>
</div>

Repeat in anonymous content (usage in XBL)

You can use repeat elements inside anonymous content to create powerful new widgets. In this scenario, though, you should use the anonid attribute to identify the repeat element that has been placed inside anonymous content.

<head>
  <xbl:bindings>
    <xbl:binding id="grid">
      <xbl:content>
        <xf:repeat xbl:inherits="bind, model, nodeset" anonid="anonidGridRepeat">
          <xf:trigger>
            <xf:label>R</xf:label>
            <xf:delete ev:event="DOMActivate" at="index('anonidGridRepeat')"
                     xbl:inherits="model, bind, nodeset"/>
          </xf:trigger>
        </xf:repeat>
      </xbl:content>
    </xbl:binding>
  </xbl:bindings>

  <style>
    div.grid {
       -moz-binding: url('#grid');
    }
  </style>

  <xf:model>
    <xf:instance>
      <data xmlns="">
        <repeat>
          <item>
            <input>Input1</input>
          </item>
          <item>
            <input>Input2</input>
          </item>
          <item>
            <input>Input3</input>
          </item>
        </repeat>
      </data>
    </xf:instance>
  </xf:model>
</head>

<body>
  <xf:repeat nodeset="/data/repeat/item" id="gridRepeat">
    <xf:input ref="input"/>
  </xf:repeat>

  <br/>
  <div class="grid" nodeset="/data/repeat/item"/>
</body>