Search code examples
orbeonxforms

How come that when inserting a new row in a repeat with a bind attribute the repeat index is not updated to the newly inserted row in orbeon xforms?


Our software generates XForms. For repeating structures it generates xf:repeat elements with a bind attribute referring to the binding model to determine its repeat collection. From the xforms specification we understand that the repeat index should always be updated to the last inserted row, but this is not what is happening. When using the ref or nodeset attribute for the repeat, the repeat index is updated as expected.

Small example to demonstrate this:

<?xml version="1.0" encoding="UTF-8"?>
<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml"
	xmlns:ev="http://www.w3.org/2001/xml-events"
	xmlns:xf="http://www.w3.org/2002/xforms"
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
	xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
	xmlns:idc="http://www.inventivedesigners.com/xbl"
	xmlns:exf="http://www.exforms.org/exf/1-0"
	xmlns:saxon="http://saxon.sf.net/">
<xhtml:head>
	<xhtml:meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
	<xhtml:title>Test</xhtml:title>

	<xf:model id="m-default">
		
		<xf:instance id="i-default">
			<data xmlns="">
				<repeat>
					<id>1</id>
				</repeat>
			</data>
		</xf:instance>

		<xf:instance id="i-counter">
			<form xmlns="">
				<counter>1</counter>
			</form>
		</xf:instance>

		<!-- bindings -->
		<xf:bind nodeset="repeat" id="repeat-bind" />

	</xf:model>

</xhtml:head>
<xhtml:body style="width: 80%; margin-left: auto; margin-right: auto;">
		
		<xhtml:table style="border: 1px solid black; margin-top: 50px;">
			<xhtml:tbody>
				<xf:repeat id="my_repeat" bind="repeat-bind">
					<xhtml:tr>
						<xhtml:td>
							<xf:output ref="id" />
						</xhtml:td>
					</xhtml:tr>
				</xf:repeat>
			</xhtml:tbody>
		</xhtml:table>
		
		<xf:trigger>
			<xf:label>Insert</xf:label>
			<xf:action ev:event="DOMActivate">
				<xf:setvalue value="number(.) + 1" ref="instance('i-counter')/counter"/>
				<xf:insert position="after" nodeset="repeat" at="index('my_repeat')"/>
				<xf:setvalue value="instance('i-counter')/counter" ref="repeat[last()]/id"/>
			</xf:action>
		</xf:trigger>
		
		<fr:xforms-inspector/>
</xhtml:body>
</xhtml:html>

If you press the button four times you will see that the order is 1,4,3,2 when we expect 1,2,3,4. When using the ref attribute on the repeat the output is as expected.

I tested this with Orbeon 4.4 and the latest 4.8 but the behaviour is the same. What is the reason for the difference between using bind and ref?


Solution

  • I updated the github issue with an explanation of why it is happening.

    As a workaround, you can use xf:setindex to explicitly set the repeat index after having inserted the new node in the data.