Reputation: 15863
I'd like to ask the user via an xf:input, "how many items" do you want in a certain repeat, and then, based on the user's response, present a repeat with that number of rows (which I guess would also be generated in the xf:instance).
I'm familiar with using triggers to insert and delete rows.
What I'm asking here is how to prompt the user for the initial number of rows to be created and presented.
For example, suppose the user wanted 10 rows. I guess the repeated data could be made not relevant, until they'd answered that question, and when they answer it, some action could dynamically create the rows, and then make the repeated data relevant.
But how to do this?
Update 20 Dec
The markup below presents an input field, and in betterform, does add rows to the instance when the button is pressed. However, betterForm doesn't display the data in the UI (though I guess this is strictly a separate question). I haven't tried other implementations.
<xhtml:head>
<xf:model id="m">
<xf:instance id="main-instance">
<data>
<items>
<item1>item 11</item1>
<item2>item 12</item2>
<item3>item 13</item3>
</items>
</data>
</xf:instance>
<xf:instance id="variable">
<variable xmlns="">
<iteration-count/>
</variable>
</xf:instance>
</xf:model>
</xhtml:head>
<xhtml:body>
<!-- Simple field to enter the number of iterations -->
<xf:input ref="instance('variable')/iteration-count">
<xf:label>How many iterations?</xf:label>
</xf:input>
<xf:trigger>
<xf:label>Insert with while</xf:label>
<xf:action ev:event="DOMActivate">
<xf:action while="instance('variable')/iteration-count != 0">
<xf:insert ev:event="DOMActivate" nodeset="items"/>
<xf:setvalue ref="instance('variable')/iteration-count" value=". - 1"/>
</xf:action>
<!--<xf:refresh model="m"/>-->
</xf:action>
</xf:trigger>
<table>
<tbody id="r-attrs" xf:repeat-nodeset="items">
<tr>
<td>
<xf:output ref="item1"></xf:output>
</td>
<td>
<xf:output ref="item2"></xf:output>
</td>
<td>
<xf:output ref="item3"></xf:output>
</td>
</tr>
</tbody>
</table>
</xhtml:body>
Upvotes: 1
Views: 958
Reputation: 1523
The while and the iterate attributes of an action will repeat this action.
Upvotes: 2
Reputation: 7857
You are asking two separate questions if I understand well:
Here are
To prompt the user, you could use a dialog (xforms:dialog
is standardized by XForms 2.0, and Orbeon Forms supports the xxforms:dialog
extension). You could also use an xforms:switch
to show/hide the field vs. the repeat.
Once the value is obtained, you can, as Alain says, the use the while
or the iterate
attribute to perform the insert action a number of times. Or, if you have XPath 2.0, you can use a for
in the origin
expression.
Here is a full example that shows two ways of inserting:
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events">
<xh:head>
<xf:model>
<xf:instance id="repeats">
<repeats/>
</xf:instance>
<xf:instance id="count">
<count/>
</xf:instance>
</xf:model>
</xh:head>
<xh:body>
<!-- Simple field to enter the number of iterations -->
<xf:input ref="instance('count')">
<xf:label>How many iterations?</xf:label>
</xf:input>
<!-- Variant 1 -->
<xf:trigger>
<xf:label>Insert with for</xf:label>
<xf:insert
ev:event="DOMActivate"
if="instance('count') castable as xs:integer"
context="instance('repeats')"
ref="repeat"
origin="for $i in 1 to instance('count')
return xf:element('repeat')"/>
</xf:trigger>
<!-- Variant 2 -->
<xf:trigger>
<xf:label>Insert with while</xf:label>
<xf:insert
ev:event="DOMActivate"
if="instance('count') castable as xs:integer"
context="instance('repeats')"
while="count(repeat) lt xs:integer(instance('count'))"
ref="repeat"
origin="xf:element('repeat')"/>
</xf:trigger>
<xf:trigger>
<xf:label>Clear</xf:label>
<xf:delete ev:event="DOMActivate" ref="instance('repeats')/*"/>
</xf:trigger>
<!-- Your repeat -->
<xf:repeat ref="repeat">
<xf:output value="position()"/>
</xf:repeat>
</xh:body>
</xh:html>
Upvotes: 1
Reputation: 25034
One way to get the information from the user is to bind an input widget to an element in an ancillary document (I often call that document ui
since it holds user-interface status info) and controlling insertion and display from that. If you want to force the user to provide a value, you can make it default to 0; if you don't, you can provide some plausible default number which the user can override if they wish.
Upvotes: 1