bound-repeat
An HTML content command that iterates through all items of a Collection and produces copies of its host element to match the items in the Collection. If the content is displayed on a Screen, the user is able to modify the Collection by adding, removing and reordering the items, with this modified Collection then saved back into the variable context upon the Screen being submitted. With other HTML content commands capable of modifying Screen data values, such as bound-value, properties of the Collection's items may be modified alongside the Collection itself.
The expression of bound-repeat
's primary attribute should refer to a Screen data variable with a Collection as its value. For compatibility reasons, the primary expression may also refer to a variable that is not declared as Screen data, but in this case the expression must only consist of a single variable name, eg. "queryResults", but not "data.relatedItems" or "opportunity['items']". The variable will also be automatically declared as Screen data in this case.
The resolved value of the primary attribute is the Collection this command will be iterating through. For every item in this Collection, a copy of the host element is produced and these copies are placed right after each other in the document structure. Should the Collection value change in any way while the Screen is displayed, the repeated structure produced by this command will immediately change to reflect the new state of the Collection. While there are other ways for the Collection to be changed in this manner, the most likely cause of that occurring is bound-repeat's own control buttons being used.
If bound-repeat
is evaluated in uneditable content (a composeContent command whose editable
attribute is false
does this), this content command's functionality becomes exactly that of its "not-bound" kin, the HTML content command repeat
.
Modifying the repeated
Users are able to modify bound-repeat
's Collection through control buttons that appear when the mouse cursor is over the host element or any of its copies - this sets the Collection item corresponding to the element as the target of the buttons' effects. There are four buttons available with the following effects:
Add - Adds a new item into the Collection. The new item will be based on the resolved value of the
bound-repeat-item-template
secondary attribute, or the first item of the Collection. The item will be placed after the targeted item.Remove - Removes the targeted item from the Collection.
Move up & Move down - Changes the targeted item's position in the Collection, either increasing or decreasing its index by one.
All of these modifications of the Collection are immediately reflected in the set of repeated elements; remove an item and its corresponding table row, paragraph or such will also be gone immediately. If users should not be able to do these kinds of modifications, the bound-repeat-show-controls
secondary attribute may be used to make the control buttons not appear.
There are also commands that can be used to replicate the functions of these control buttons in other elements of the Screen. These are bound-repeat-add and bound-repeat-remove, for the Add and Remove functions respectively. These will function even if bound-repeat
's own control buttons are unavailable. Additionally, a control for sorting the items in bound-repeat
's Collection may be created with the bound-repeat-sort command.
An Undo control may also be activated through the bound-repeat-undo-control-id
attribute. This control has the effect of restoring the items removed through the Remove function, one at a time and in the order of restoring the most recently removed first. The Undo control differs from the others as its appearance is completely up to the Screen's designer. The bound-repeat-undo-control-id
needs to define the ID of an element on the Screen, and that element needs to then contain an element with the class undo-click
- clicking this element will execute the Undo functionality. This control will only be visible if there is an item to restore.
The Collection is empty
In case the resolved value of the primary attribute is a Collection with no items, or a user removes all of the items with the Remove button, bound-repeat
will not cease to exist. It will display a dimmed placeholder version of its repeated element and if the mouse cursor is placed over it, the control buttons appear with only Add being available. This allows the user to add the first item to the Collection. Note that should bound-repeat-show-controls
be false
, this placeholder functionality is disabled, although it is still possible to add the first item through an Add control created with bound-repeat-add
.
This content command produces a local variable context for the commands evaluated within the iteration rounds, but only if evaluated in HTML content declared as uneditable. This local context's primary feature is that it contains one of the Collection's items for the other commands to access. A new context is created at the start of every round of the iteration process, and then terminated at the end of the round.
This command has a priority of 1000 if evaluated in HTML content declared as uneditable. Otherwise its priority can be considered to be lower compared to all other HTML content commands besides other commands of the "bound" series, which operate at a lower priority.
Child commands
bound-content
Optional. This content command can be used to display, but not edit, values within the Collection items.bound-editor
Optional. This content command can be used to edit any HTML Values within the Collection items.bound-if
Optional. This content command can be used to make an element conditonal based on a value within the Collection items.bound-select
Optional. This content command can be used to edit values with limited options within the Collection items.bound-value
Optional. This content command can be used to edit String, Boolean, Number and Date values within the Collection items.
Secondary attributes
bound-repeat-var | ||
---|---|---|
Required | Value type | EL-evaluated |
Yes | String | No |
The value of this attribute defines the name of the Screen data variable with the the currently iterated item of the Collection as its value. This variable is only accessible to content commands inside |
bound-repeat-name | ||
---|---|---|
Required | Value type | EL-evaluated |
Yes | String | No |
The value of this attribute defines a name by which other content commands outside this Note that this name has to be unique among all |
bound-repeat-show-controls | ||
---|---|---|
Required | Value type | EL-evaluated |
No | Boolean | Yes |
This attribute may be used to disable the controls for modifying the Collection. If the resolved value is Note that while If not defined, value of |
bound-repeat-disabled-controls | ||
---|---|---|
Required | Value type | EL-evaluated |
No | String | No |
This attribute may be used to disable the controls for modifying the Collection individually. The resolved value is expected be a String naming the controls to disable, separated with semicolons. The names are as follows:
Naming all three causes the effect to be the same as Note that while If not defined, no controls are disabled. |
bound-repeat-item-template | ||
---|---|---|
Required | Value type | EL-evaluated |
No | Map | Yes |
This attribute defines the template which new items added to the Collection are based on. The resolved value Map should therefore contain the keys the items in the Collection are expected to have. Any values associated with the keys do not matter, as all new items have empty values for their keys regardless of the values in this template Map. If not defined, |
bound-repeat-scroll-to-new | ||
---|---|---|
Required | Value type | EL-evaluated |
No | Boolean | Yes |
This attribute can enable a feature that causes the parent element of bound-repeat's host element to be scrolled so that a newly created item is in the view. This feature is enabled if the resolved value is Note that for this feature to work, the host element's parent must be positioned ie. the parent must not have the CSS property "position" set to the value of "static". If undefined, value of |
bound-repeat-confirm-removal | ||
---|---|---|
Required | Value type | EL-evaluated |
No | Boolean | Yes |
This attribute can enable a feature that causes a dialog to appear when removing an item, confirming the removal operation. This feature is enabled if the resolved value is If undefined, value of |
bound-repeat-undo-control-id | ||
---|---|---|
Required | Value type | EL-evaluated |
No | String | Yes |
This attribute can be used to enable an additional control that allows users to undo item removals, restoring the removed items one at a time. The resolved value is expected to define the id of an element within the Screen - please see the command's main documentation for more details. If undefined, the Undo control is not available. |
Examples
The bound-repeat
command exists to allow users to edit Collections, and in most cases you probably want to also have some other Screen data -manipulating commands like bound-value
to edit the items within the Collection as well. Here is a simple table displaying the "items" Collection and allowing the "name" and "price" values of each item to be edited:
<table><tr dyn-bound-repeat="items" dyn-bound-repeat-var="item"><td><input dyn-bound-value="item.name" /></td><td><input dyn-bound-value="item.price" /></td></tr></table>
If there is a possibility that bound-repeat
's Collection is initially empty and the Add control has not been disabled, the bound-repeat-item-template
attribute should be used to tell bound-repeat
what kind of an item it should be adding to the Collection when requested. Using the previous example, the items of the "items" Collection are Maps that, at the very least, contain the keys "name" and "price". Therefore the item template given to bound-repeat
should be a Map like this:
<setMap var="itemTemplate"><addMapEntry key="name" value="-"><addMapEntry key="price" value="-">
A useful addition for bound-repeat
is the Undo functionality, at least if the Remove control is not disabled. The appearance of the Undo control can be freely designed, the only requirement is that one element within the control element specified with bound-repeat-undo-control-id
needs to have the undo-click
class. Here's the "items" bound-repeat
with an Undo added, as well as the item template set:
<div class="example-undo-control"><div class="undo-click"><span>Undo removal</span></div></div><table><tr dyn-bound-repeat="items" dyn-bound-repeat-var="item" dyn-bound-repeat-item-template="itemTemplate" dyn-bound-repeat-undo-control-id="'example-undo-control'" ><td><input dyn-bound-value="item.name" /></td><td><input dyn-bound-value="item.price" /></td></tr></table>
Using "of-repeat"
The bound-repeat-name
attribute is for other commands to link themselves to the bound-repeat
. The Screen data -manipulating content commands that can be used within bound-repeat to edit its items have an "of-repeat" attribute that give these commands more freedom in the placement of their host elements in relation to the bound-repeat
's element, as they no longer have to placed inside repeat's element. Here's a simple repeat structure with bound-value
:
<div bound-repeat="products" bound-repeat-var="product" bound-repeat-name="productsRepeat"><input bound-value="product.name"/><input type="number" bound-value="product.quantity" /></div>
And here's the same structure with one of the inputs taken outside and given bound-repeat
's bound-value-of-repeat
secondary attribute, with its value matching the name of the repeat:
<div bound-repeat="products" bound-repeat-var="product" bound-repeat-name="productsRepeat"><input bound-value="product.name"/></div><input type="number" bound-value="targetItem.quantity" bound-value-of-repeat="productsRepeat"/>
The input outside the bound-repeat
will now display the "quantity" of the item whose repeated element the user's mouse cursor is over. Note that its expression now uses "targetItem" instead of "product" to refer to the target item - this is a fixed variable name to be used by these linked commands whose value is always the currently targeted item.
One use for this feature is with the modal command; an element with modal
may be placed within the bound-repeat
, and a bound-value
with bound-value-of-repeat
can be in the associated modal's contents. Now when the modal-calling element is clicked in the repeated content, the modal's bound-value
will display a value of that particular item. The previous structure could then be modified to be like this, with a modal and a modal-calling button now added:
Screen:<div bound-repeat="products" bound-repeat-var="product" bound-repeat-name="productsRepeat"><input bound-value="product.name"/><button type="button" dyn-modal="doc['Quantity Modal']" dyn-modal-height="300" dyn-modal-width="300"/></div>Modal:<input type="number" bound-value="targetItem.quantity" bound-value-of-repeat="productsRepeat"/>
The links between inputs and the repeat may also be used to define values for a new item to be added to the Collection. Together with bound-repeat-add
, this makes it possible to have a separate section on the Screen, or a modal, for defining and creating new items. To have an input modify this future item instead of the currently targeted item, have the related command's expression refer to the item variable using the variable name "nextItem". Here is an example of that linked to the product-displaying bound-repeat
:
<input bound-value="nextItem.name" bound-value-of-repeat="productsRepeat"/><input type="number" bound-value="nextItem.quantity" bound-value-of-repeat="productsRepeat"/><button dyn-repeat-add="productsRepeat">Add item</button><div bound-repeat="products" bound-repeat-var="product" bound-repeat-name="productsRepeat"><p>Product name: <span bound-content="product.name"/></span></p><p>Quantity: <span bound-content="product.quantity"/></span></p></div>
The inputs above now set the "name" and "quantity" of the item created when the button below them is clicked.