# Repeat, insert and delete

## Basics

A very common requirement of user interfaces consists in repeating visual elements, such as rows in a table or entries in a list. Those repeated sections usually (but not always) have an homogeneous aspect: they all have the same or a very similar structure. For example, multiple table rows will differ only in the particular content they display in their cells. An example of this is an invoice made of lines with each a description, unit price, and quantity.

XForms provides a very powerful mechanism to implement such repeated structures: the `<xf:repeat>` action. You use `<xf:repeat>` around XHTML elements or XForms controls. For example, to repeat a table row, you write:

```markup
<xf:repeat>
    <xh:tr>
        ...
    </xh:tr>
</xf:repeat>
```

This is not enough to be functional code: you need to indicate to the `<xf:repeat>` element how many repetitions must be performed. This is done not by supplying a simple count value, but by binding the the element to a node-set with the `ref` attribute. Consider the following XForms instance:

```markup
<xf:instance id="employees-instance">
    <employees>
        <employee>
            <first-name>Alice</first-name>
        </employee>
        <employee>
            <first-name>Bob</first-name>
        </employee>
        <employee>
            <first-name>Marie</first-name>
        </employee>
    </employees>
</xf:instance>
```

Assuming you want to produce one table row per employee, add the following `ref` attribute:

```markup
<xf:repeat ref="instance('employees-instance')/employee">
    <xh:tr>...</xh:tr>
</xf:repeat>
```

This produces automatically three `xh:tr` rows. Note that we explicitly use the XForms `instance()` function, but you may not have to do so if that instance is already in scope. Then you display in each row the content of the `first-name` element for each employee:

```markup
<xf:repeat ref="instance('employees-instance')/employee">
    <xh:tr>
        <xh:td>
            <xf:output ref="first-name"/>
        </xh:td>
    </xh:tr>
</xf:repeat>
```

This works because for each iteration, the *context node* for the `ref` attribute changes: during the first iteration, the context node is the first `employee` element of the XForms instance; during the second iteration, the second `employee` element, and so on.

## Repeat index

Each `<xf:repeat>` element has an associated index, representing the notion of a currently selected repeat iteration. This information can be used in CSS for example to highlight the currently selected iteration. The current index for a given repeat can be obtained with the XPath `index()` function.

Each nested repeat keeps its own separate index value.

The `index()` function should not be confused wit the `position()` function.

*NOTE: XForms 1.1 does not explicitly limit in what type of XPath expressions* `index()` *can be used. However, in Orbeon Forms, it is strongly advised at the moment to only use* `index()` *within actions, and to avoid using it in control bindings and binds, as doing so may yield unpredictable results.*

## Deleting iterations with the delete action

`<xf:repeat>` may be used purely for display purposes, but it can also be used for interactively editing repeated data. This includes allowing the user to delete and insert iterations. Two XForms actions are used for this purpose: `<xf:delete>` and `<xf:insert>`.

`<xf:delete>` is provided with a `ref` attribute pointing to the collection of nodes to delete. It also has an optional `at` attribute, which contains an XPath expression returning the index of the element to delete. See how `<xf:delete>` is used in these scenarios:

```markup
<!-- This deletes the last element of the collection -->
<xf:delete ref="employees" at="last()"/>

<!-- This deletes the first element of the collection -->
<xf:delete ref="employees" at="1"/>

<!-- This deletes the currently selected element of the collection (assuming the repeat id 'employee-repeat') -->
<xf:delete ref="employees" at="index('employee-repeat')"/>

<!-- This deletes all elements of the collection -->
<xf:delete ref="employees"/>
```

*NOTE: Prior to XForms 1.1, the* `at` *attribute was mandatory. Since XForms 1.1, it is optional, and if omitted the* `ref` *attribute specifies all the nodes to remove.*

## Inserting iterations with the insert action

*See also the* [*Insert a new item into a repeat*](http://wiki.orbeon.com/forms/how-to/logic/repeat-insert-position) *how-to guide.*

`<xf:insert>` has a `ref` attribute pointing to the collection into which the insertion must take place. If no `origin` attribute is specified, `<xf:insert>` then considers the *last* element of that collection (and all its content if any) as a *template* for the new element to insert: it duplicates it and inserts it into the collection at a position you specify. In this case, the last element of a collection acts as a *template* for insertions:

```markup
<!-- Insert a copy of the template before the last element of the collection -->
<xf:insert ref="employees" at="last()" position="before"/>

<!-- Insert a copy of the template after the last element of the collection -->
<xf:insert ref="employees" at="last()" position="after"/>

<!-- Insert a copy of the template before the first element of the collection -->
<xf:insert ref="employees" at="1" position="before"/>

<!-- Insert a copy of the template after the first element of the collection -->
<xf:insert ref="employees" at="1" position="after"/>
<xf:insert ref="employees" at="last()" position="after"/>

<!-- Insert a copy of the template before the currently selected element of the collection -->
<xf:insert ref="employees" at="index('employee-repeat')" position="before"/>

<!-- Insert a copy of the template after the currently selected element of the collection -->
<xf:insert ref="employees" at="index('employee-repeat')" position="after"/>
```

The `at` attribute contains an XPath expression returning the index of the element before or after which the insertion must be performed. The `position` element contains either `after` or `before`, and specifies whether the insertion is performed before or after the element specified by the `at` attribute.

As an extension to XForms 1.1, Orbeon Forms supports inserting an element into a document node:

```markup
<xf:insert context="instance()/root()" origin="instance('other')">
```

This is particularly useful in conjunction with the `xxf:create-document()` function.

## Using a trigger to execute actions

Insertions and deletions are typically performed when the user of the application presses a button, with the effect of adding a new repeated element before or after the currently selected element, or of deleting the currently selected element. You use an `xf:trigger` control and the XPath `index()` function for that purpose:

```markup
<xf:trigger>
    <xf:label>Add</xf:label>
    <xf:action ev:event="DOMActivate">
        <xf:insert ref="employees" at="index('employee-repeat')" position="after"/>
    </xf:action>
</xf:trigger>
```

or:

```markup
<xf:trigger>
    <xf:label>Delete</xf:label>
    <xf:action ev:event="DOMActivate">
        <xf:delete ref="employees" at="index('employee-repeat')"/>
    </xf:action>
</xf:trigger>
```

Note that we use `xf:action` as a container for `<xf:insert>` and `<xf:delete>`. Since there is only one action to execute, `xf:action` is not necessary, but it may increase the legibility of the code. It is also possible to write:

```markup
<xf:trigger>
    <xf:label>Add</xf:label>
    <xf:insert ev:event="DOMActivate" ref="employees" at="index('employee-repeat')" position="after"/>
</xf:trigger>
```

or:

```markup
<xf:trigger>
    <xf:label>Delete</xf:label>
    <xf:delete ev:event="DOMActivate" ref="employees" at="index('employee-repeat')"/>
</xf:trigger>
```

Notice in that case how `ev:event="DOMActivate"` has been moved from the enclosing `xf:action` to the `<xf:insert>` and `<xf:delete>` elements.

## Nested repeats

It is often desirable to nest repeat sections. Consider the following XForms instance representing a company containing departments, each containing a number of employees:

```markup
<xf:instance id="departments">
    <departments>
        <department>
            <name>Research and Development</name>
            <employees>
                <employee>
                    <first-name>John</first-name>
                </employee>
                <employee>
                    <first-name>Mary</first-name>
                </employee>
            </employees>
        </department>
        <department>
            <name>Support</name>
            <employees>
                <employee>
                    <first-name>Anne</first-name>
                </employee>
                <employee>
                    <first-name>Mark</first-name>
                </employee>
                <employee>
                    <first-name>Sophie</first-name>
                </employee>
            </employees>
        </department>
    </departments>
</xf:instance>
```

This document clearly contains two nested sections subject to repetition:

* **Departments:** a node-set containing all the `department` elements can be referred to with the following XPath expression: `instance('departments')/department`.
* **Employees:** a node-set containing all the `employee` elements can be referred to with the following XPath expression: `instance('departments')/department/employees/employee`. However, if the *context node* of the XPath expression points to a particular `department` element, then the following *relative* XPath expression refers to all the `employee` elements under that `department` element: `employees/employee`.

Following the example above, here is how departments and employees can be represented in nested tables with xf:

```markup
<xh:table>
    <xf:repeat ref="instance('departments')/department">
        <xh:tr>
            <xh:td>
                <xf:output ref="name"/>
            </xh:td>
            <xh:td>
                <xh:table>
                    <xf:repeat ref="employees/employee">
                        <xh:tr>
                            <xh:td>
                                <xf:output ref="first-name"/>
                            </xh:td>
                        </xh:tr>
                    </xf:repeat>
                </xh:table>
            </xh:td>
        </xh:tr>
    </xf:repeat>
</xh:table>
```

In the code above, the second `<xf:repeat>`'s `ref` expression is interpreted relatively to the `department` element of the parent `<xf:repeat>` for each iteration of the parent's repetition. During the first iteration of the parent, the "Research and Development" department is in scope, and `employees/employee` refers to the two employees of that department, John and Mary. During the second iteration of the parent, the "Support" department is in scope, and `employees/employee` refers to the three employees of that department, Anne, Mark and Sophie.

## Iterating over plain values

XForms 1.1 only specifies iterating over instance data nodes (elements or attributes). Orbeon Forms supports iterating over values, for example:

```markup
<xf:repeat ref="1 to 10">
    <xf:output value="position()"/>
    <xf:output value="."/>
</xf:repeat>
```

In this case, the context item within the repeat is a number, not a node.

*NOTE: This ability is also part of the XForms 2 specification.*

## Evaluation of initial values upon insert

Orbeon Forms supports the `xxf:default` extension attribute on `xf:bind` to specify [dynamic initial values](https://doc.orbeon.com/~/revisions/-LFrzxlvP9UXA6_RDYI9/core/binds#dynamic-initial-values).

By default (no pun intended), `xxf:default` does not apply to the newly inserted nodes. But by setting the `xxf:defaults` attribute (note the plural "defaults") on `xf:insert` to `true`, this behavior can be changed, and any `xxf:default` pointing to a newly-inserted node is re-evaluated during the next recalculation.

Consider the following example where the bind points to any `<value>` element child of the root element, and sets a dynamic initial value:

```markup
<xf:instance>
  <data>
      <value/>
  </data>
</xf:instance>

<xf:bind
    ref="instance()/value"
    xxf:default="count(//*)"/>
```

The data looks like this after initialization:

```markup
<data>
    <value>2</value>
</data>
```

Running the following insert adds a new `<value>` element after the first one:

```markup
<xf:insert
    ref="instance()/value"
    position="after"
    origin="xf:element('value')"
    xxf:defaults="true"/>
```

Because the action specifies `xxf:defaults="true"`, the first `value` element is unchanged, but the new `<value>` element gets its dynamic initial value set:

```markup
<data>
    <value>2</value>
    <value>3</value>
</data>
```

## See also

* [Dynamic initial values](https://doc.orbeon.com/~/revisions/-LFrzxlvP9UXA6_RDYI9/core/binds#dynamic-initial-values)
* [Grid component](https://doc.orbeon.com/~/revisions/-LFrzxlvP9UXA6_RDYI9/form-runner/components/grid)
