Validate field in repeated grid with webservice - orbeon

I am using a webservice through an action in a field to retrieve some aditional data as well as validate the user input. The validation is done by storing in a instance the validation status and make the input field to check that the code is not present to be valid. This works correctly as long as I don't try to use a repeated grid. When a repeated grid is used the same instance is used for all the repeated fields. The webservice data is loaded correctly independendtly, but the validation is shared between all of them. How can I adjust the code to work properly in repeated grids?
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:exf="http://www.exforms.org/exf/1-0"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder">
<xh:head>
<xh:title>repeated_ws</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<!-- Main instance -->
<xf:instance id="fr-form-instance" xxf:exclude-result-prefixes="#all">
<form>
<section-1>
<grid-4>
<grid-4-iteration>
<userId/>
<name/>
<address/>
</grid-4-iteration>
</grid-4>
</section-1>
</form>
</xf:instance>
<xf:instance id="repeatable-uid-instance">
<valid/>
</xf:instance>
<!-- Bindings -->
<xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
<xf:bind id="section-1-bind" name="section-1" ref="section-1">
<xf:bind id="grid-4-bind" ref="grid-4" name="grid-4">
<xf:bind id="grid-4-iteration-bind" ref="grid-4-iteration" name="grid-4-iteration">
<xf:bind id="userId-bind" ref="userId" name="userId">
<xf:constraint id="validation-9-validation"
value="instance('repeatable-uid-instance')/valid != 'not exist'"/>
</xf:bind>
<xf:bind id="name-bind" ref="name" name="name" readonly="true()"/>
<xf:bind id="address-bind" ref="address" name="address" readonly="true()"/>
</xf:bind>
</xf:bind>
</xf:bind>
</xf:bind>
<!-- Metadata -->
<xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
<metadata>
<application-name>test</application-name>
<form-name>repeated_ws</form-name>
<title xml:lang="en">repeated_ws</title>
<description xml:lang="en"/>
<singleton>false</singleton>
</metadata>
</xf:instance>
<!-- Attachments -->
<xf:instance id="fr-form-attachments" xxf:exclude-result-prefixes="#all">
<attachments>
<css mediatype="text/css" filename="" size=""/>
<pdf mediatype="application/pdf" filename="" size=""/>
</attachments>
</xf:instance>
<!-- All form resources -->
<!-- Don't make readonly by default in case a service modifies the resources -->
<xf:instance id="fr-form-resources" xxf:readonly="false" xxf:exclude-result-prefixes="#all">
<resources>
<resource xml:lang="en">
<userId>
<label>userId</label>
<hint/>
<alert>custom error</alert>
</userId>
<name>
<label>name</label>
<hint/>
</name>
<address>
<label>address</label>
<hint/>
</address>
<section-1>
<label>Untitled Section</label>
</section-1>
</resource>
</resources>
</xf:instance>
<!-- Utility instances for services -->
<xf:instance id="fr-service-request-instance" xxf:exclude-result-prefixes="#all">
<request/>
</xf:instance>
<xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
<response/>
</xf:instance>
<xf:instance xxf:readonly="true" id="grid-4-template">
<grid-4-iteration>
<userId/>
<name/>
<address/>
</grid-4-iteration>
</xf:instance>
<xf:instance id="get-user-data-instance" class="fr-service"
xxf:exclude-result-prefixes="#all">
<body xmlns:secure="java:org.orbeon.oxf.util.SecureUtils"
xmlns:frf="java:org.orbeon.oxf.fr.FormRunner"
xmlns:p="http://www.orbeon.com/oxf/pipeline"
xmlns:fbf="java:org.orbeon.oxf.fb.FormBuilder"><bsn/></body>
</xf:instance>
<xf:submission id="get-user-data-submission" class="fr-service"
ref="instance('fr-service-request-instance')"
resource="http://localhost:8082/rest/getUserData"
method="post"
serialization="application/xml"
mediatype="application/xml"
replace="instance"
instance="fr-service-response-instance"/>
<xf:action id="call-get-user-data-binding">
<!-- React to event... on control... -->
<xf:action ev:event="xforms-value-changed xforms-enabled" ev:observer="userId-control"
if="true()">
<!-- Service to call -->
<xf:send submission="get-user-data-submission"/>
</xf:action>
<!-- Request actions -->
<xf:action ev:event="xforms-submit" ev:observer="get-user-data-submission">
<!-- Get reference to initial request -->
<xf:var name="request-instance-name" value="'get-user-data-instance'" as="xs:string"/>
<!-- Copy over to read-write request instance -->
<xf:insert ref="instance('fr-service-request-instance')"
origin="saxon:parse(instance($request-instance-name))"/>
<!--<xf:insert ref="instance('fr-service-request-instance')" origin="instance($request-instance-name)"/>-->
<!-- Set values if needed -->
<xf:action context="instance('fr-service-request-instance')">
<xf:action class="fr-set-service-value-action">
<xf:var name="control-name" value="'userId'"/>
<xf:var name="path" value="/bsn"/>
</xf:action>
<!-- Setvalue actions will be here -->
</xf:action>
</xf:action>
<!-- Response actions -->
<xf:action ev:event="xforms-submit-done" ev:observer="get-user-data-submission"
context="instance('fr-service-response-instance')">
<xf:action class="fr-set-control-value-action">
<xf:var name="control-name" value="'name'"/>
<xf:var name="control-value" value="/data/name"/>
</xf:action>
<xf:action class="fr-set-control-value-action">
<xf:var name="control-name" value="'address'"/>
<xf:var name="control-value" value="/data/address"/>
</xf:action>
<xf:insert origin="instance('fr-service-response-instance')"
ref="instance('repeatable-uid-instance')"/>
<!-- Response actions will be here -->
</xf:action>
</xf:action>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:p="http://www.orbeon.com/oxf/pipeline">
<fr:section id="section-1-control" bind="section-1-bind">
<xf:label ref="$form-resources/section-1/label"/>
<fr:grid id="grid-4-grid" bind="grid-4-bind" repeat="content" min="1"
template="instance('grid-4-template')">
<xh:tr>
<xh:td>
<xf:input id="userId-control" bind="userId-bind">
<xf:label ref="$form-resources/userId/label"/>
<xf:hint ref="$form-resources/userId/hint"/>
<xf:alert ref="$form-resources/userId/alert" validation="validation-9-validation"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:input id="name-control" bind="name-bind">
<xf:label ref="$form-resources/name/label"/>
<xf:hint ref="$form-resources/name/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:input id="address-control" bind="address-bind">
<xf:label ref="$form-resources/address/label"/>
<xf:hint ref="$form-resources/address/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
</xh:tr>
</fr:grid>
</fr:section>
</fr:body>
</fr:view>
</xh:body>

What version of Orbeon Forms are you using? Since 4.5, control resolution follows repeats in actions, so the result from your service should only change the name and address of the current iteration, i.e. the one in which the userId changed and triggered the action to run, which seems to be what you are looking for.

Related

XPath to check if control value valid

Is there a way to check if a control value is valid (a value is present if required and the value is valid)? I have tried using xf:valid and xxf:valid, but none work as I expected (seem to have to change another, unrelated control for it to redo the calculate value.
2016.2 form builder example form - email-valid value correct once change value of control-5.
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:exf="http://www.exforms.org/exf/1-0"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder">
<xh:head>
<xh:title>Untitled Form</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<!-- Main instance -->
<xf:instance id="fr-form-instance" xxf:exclude-result-prefixes="#all" xxf:index="id">
<form>
<section-1>
<email-required/>
<email/>
<email-valid/>
<control-5/>
</section-1>
</form>
</xf:instance>
<!-- Bindings -->
<xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
<xf:bind id="section-1-bind" name="section-1" ref="section-1">
<xf:bind id="email-required-bind" name="email-required" ref="email-required"
xxf:whitespace="trim"/>
<xf:bind id="email-bind" ref="email" name="email" type="xf:email" xxf:whitespace="trim"
required="//email-required ne ''"/>
<xf:bind id="email-valid-bind" ref="email-valid" name="email-valid"
calculate="if (xxf:valid(//email)) then 'good' else 'bad'"/>
<xf:bind id="control-5-bind" ref="control-5" name="control-5" xxf:whitespace="trim"/>
</xf:bind>
</xf:bind>
<!-- Metadata -->
<xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
<metadata>
<application-name>TEST</application-name>
<form-name>TEST</form-name>
<title xml:lang="en">Untitled Form</title>
<description xml:lang="en"/>
</metadata>
</xf:instance>
<!-- Attachments -->
<xf:instance id="fr-form-attachments" xxf:exclude-result-prefixes="#all">
<attachments>
<css mediatype="text/css" filename="" size=""/>
<pdf mediatype="application/pdf" filename="" size=""/>
</attachments>
</xf:instance>
<!-- All form resources -->
<xf:instance xxf:readonly="true" id="fr-form-resources" xxf:exclude-result-prefixes="#all">
<resources>
<resource xml:lang="en">
<section-1>
<label>Untitled Section</label>
</section-1>
<email-required>
<label>Email Required?</label>
<hint/>
</email-required>
<email>
<label>Emal</label>
<hint/>
</email>
<email-valid>
<label>Email Valid</label>
<hint/>
</email-valid>
<control-5>
<label>Random Field</label>
<hint/>
</control-5>
</resource>
</resources>
</xf:instance>
<!-- Utility instances for services -->
<xf:instance id="fr-service-request-instance" xxf:exclude-result-prefixes="#all">
<request/>
</xf:instance>
<xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
<response/>
</xf:instance>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:xbl="http://www.w3.org/ns/xbl" xmlns:p="http://www.orbeon.com/oxf/pipeline"
xmlns:oxf="http://www.orbeon.com/oxf/processors">
<fr:section id="section-1-control" bind="section-1-bind">
<xf:label ref="$form-resources/section-1/label"/>
<fr:grid>
<xh:tr>
<xh:td>
<xf:input id="email-required-control" bind="email-required-bind">
<xf:label ref="$form-resources/email-required/label"/>
<xf:hint ref="$form-resources/email-required/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
<xh:td>
<xf:input id="email-control" bind="email-bind">
<xf:label ref="$form-resources/email/label"/>
<xf:hint ref="$form-resources/email/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:output id="email-valid-control" bind="email-valid-bind">
<xf:label ref="$form-resources/email-valid/label"/>
<xf:hint ref="$form-resources/email-valid/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:output>
</xh:td>
<xh:td>
<xf:input id="control-5-control" bind="control-5-bind">
<xf:label ref="$form-resources/control-5/label"/>
<xf:hint ref="$form-resources/control-5/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
</xh:tr>
</fr:grid>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
</xh:html>
The reason this happens is the processing model in XForms:
First, data is updated and recalculated.
Second, data is revalidated.
So if you make a calculation dependent on validation, you can get into the kind of cycle you are seeing, namely that things don't happen in the order you expect. This could, possibly, be fixed by a more subtle dependency algorithm (see also this RFE), but currently this is how things must happen.
In these situations, you could use actions, something like:
<xf:setvalue
observer="email-valid-control"
event="xforms-valid"
ref="bind('email-valid-bind')"
value="true()"/>
<xf:setvalue
observer="email-valid-control"
event="xforms-invalid"
ref="bind('email-valid-bind')"
value="false()"/>
This is heavier, and requires you to use custom model logic, but it's the only reliable way right now.

Orbeon Form with repeated grid : Identify field values of same iteration

I am using Form Builder (version 4.9) to create a form containing a Repeated Grid.
I've also defined a Process button, in order to send the form's data to a Servlet (using the send() method).
My goal is to save the form data in a DB table.
I am able to receive the Form's data as XML in the servlet, but I noticed that a field having the same value in different iterations,
appears only once per value in the XML, having a 'for' attribute with multiple values (indicating the number of the value repetitions).
However, I haven't been able to find a way to match all fields of the same iteration (indicating one table row), so I am not able to store the data in the DB correctly.
For Example , when I post the following table
HEADERS : FIELD_B - FIELD_C -
ITER_1 : FIELD_B_1 - FIELD_C_1 -
ITER_2 : FIELD_B_2 - FIELD_C_2 -
ITER_2 : FIELD_B_3 - FIELD_C_1 -
I get the following XML
<?xml version="1.0" encoding="UTF-8"?>
<metadata>
<control for="e7d2bb4ac261e77159fc236e7fd922c3540756f8" name="section-1"
type="section">
<resources lang="en">
<label>Untitled Section</label>
</resources>
</control>
<control for="69ec5abdeb2df55c97bf5b1db46cce6bc841aed8" name="FIELD_A"
type="input">
<resources lang="en">
<label>FIELD_A</label>
<hint />
</resources>
<value>FIELD_A_V</value>
</control>
<control for="9749b7620379db1e8f86eeceaf52c60fa19484d2" name="FIELD_B"
type="input">
<resources lang="en">
<label>FIELD_B</label>
<hint />
</resources>
<value>FIELD_B_1</value>
</control>
<control
for="89761405fd9de1a147bdda4d2c9279062b806016 9fa491ba6b72e86919e8a02226e28572c7309311"
name="FIELD_C" type="input">
<resources lang="en">
<label>FIELD_C</label>
<hint />
</resources>
<value>FIELD_C_1</value>
</control>
<control for="9cf502968950de2af58236fe0aaaab2a4fa5ac6d" name="FIELD_B"
type="input">
<resources lang="en">
<label>FIELD_B</label>
<hint />
</resources>
<value>FIELD_B_2</value>
</control>
<control for="46337304c26fca5cf9d5e91cdf393e3d39c0fbde" name="FIELD_C"
type="input">
<resources lang="en">
<label>FIELD_C</label>
<hint />
</resources>
<value>FIELD_C_2</value>
</control>
<control for="1155463007588b06b3842c534ca678aa6f5cf665" name="FIELD_B"
type="input">
<resources lang="en">
<label>FIELD_B</label>
<hint />
</resources>
<value>FIELD_B_3</value>
</control>
</metadata>
As you can see, in iterations 1 and 3, FIELD_C contains the value FIELD_C_1.
When parsing the XML, I am not able to find the order of the values of that field. I end up with the incorrect table :
HEADERS : FIELD_B - FIELD_C -
ITER_1 : FIELD_B_1 - FIELD_C_1 -
ITER_2 : FIELD_B_2 - FIELD_C_1 -
ITER_2 : FIELD_B_3 - FIELD_C_2 -
The iterations 2 and 3 have wrong values in FIELD_C.
How can I find the correct order of the values for the repeated fields ?
I am looking for a solution that does not require manipulating the form definition outside form builder, since the forms will be created by the end user with no knowledge of XForms.
The submit button in properties-local.xml is :
<property
as="xs:string"
name="oxf.fr.detail.process.OrbeonFormsPortlet.*.*">
validate-all
then send(
property = "oxf.fr.detail.send.success",
uri = "http://localhost:8080/web/guest/testlang/-/oaed-form-requests/pop_up/{xxf:get-request-header('Orbeon-Liferay-User-Id')}",
content = "metadata",
prune = "false"
)
</property>
The complete form definition is (the form contains a field - FIELD_A - outside repeated grid which is irrelevant to the problem):
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:saxon="http://saxon.sf.net/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:exf="http://www.exforms.org/exf/1-0">
<xh:head>
<xh:title>TestRepeat</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<!-- Main instance -->
<xf:instance id="fr-form-instance" xxf:exclude-result-prefixes="#all">
<form>
<section-1>
<FIELD_A/>
<grid-3>
<grid-3-iteration>
<FIELD_B/>
<FIELD_C/>
</grid-3-iteration>
</grid-3>
</section-1>
</form>
</xf:instance>
<!-- Bindings -->
<xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
<xf:bind id="section-1-bind" name="section-1" ref="section-1">
<xf:bind id="FIELD_A-bind" name="FIELD_A" ref="FIELD_A"/>
<xf:bind id="grid-3-bind" ref="grid-3" name="grid-3">
<xf:bind id="grid-3-iteration-bind" ref="grid-3-iteration" name="grid-3-iteration">
<xf:bind id="FIELD_B-bind" ref="FIELD_B" name="FIELD_B"/>
<xf:bind id="FIELD_C-bind" ref="FIELD_C" name="FIELD_C"/>
</xf:bind>
</xf:bind>
</xf:bind>
</xf:bind>
<!-- Metadata -->
<xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
<metadata>
<application-name>OAED</application-name>
<form-name>TestRepeat</form-name>
<title xml:lang="en">TestRepeat</title>
<description xml:lang="en"/>
<singleton>false</singleton>
</metadata>
</xf:instance>
<!-- Attachments -->
<xf:instance id="fr-form-attachments" xxf:exclude-result-prefixes="#all">
<attachments>
<css mediatype="text/css" filename="" size=""/>
<pdf mediatype="application/pdf" filename="" size=""/>
</attachments>
</xf:instance>
<!-- All form resources -->
<!-- Don't make readonly by default in case a service modifies the resources -->
<xf:instance id="fr-form-resources" xxf:readonly="false" xxf:exclude-result-prefixes="#all">
<resources>
<resource xml:lang="en">
<FIELD_B>
<label>FIELD_B</label>
<hint/>
</FIELD_B>
<FIELD_C>
<label>FIELD_C</label>
<hint/>
</FIELD_C>
<section-1>
<label>Untitled Section</label>
</section-1>
<FIELD_A>
<label>FIELD_A</label>
<hint/>
</FIELD_A>
</resource>
</resources>
</xf:instance>
<!-- Utility instances for services -->
<xf:instance id="fr-service-request-instance" xxf:exclude-result-prefixes="#all">
<request/>
</xf:instance>
<xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
<response/>
</xf:instance>
<xf:instance xxf:readonly="true" id="grid-3-template">
<grid-3-iteration>
<FIELD_B/>
<FIELD_C/>
</grid-3-iteration>
</xf:instance>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:p="http://www.orbeon.com/oxf/pipeline"
xmlns:xbl="http://www.w3.org/ns/xbl">
<fr:section id="section-1-control" bind="section-1-bind">
<xf:label ref="$form-resources/section-1/label"/>
<fr:grid>
<xh:tr>
<xh:td>
<xf:input id="FIELD_A-control" bind="FIELD_A-bind">
<xf:label ref="$form-resources/FIELD_A/label"/>
<xf:hint ref="$form-resources/FIELD_A/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
<xh:td/>
</xh:tr>
</fr:grid>
<fr:grid id="grid-3-grid" bind="grid-3-bind" repeat="content" min="1"
template="instance('grid-3-template')">
<xh:tr>
<xh:td>
<xf:input id="FIELD_B-control" bind="FIELD_B-bind">
<xf:label ref="$form-resources/FIELD_B/label"/>
<xf:hint ref="$form-resources/FIELD_B/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
<xh:td>
<xf:input id="FIELD_C-control" bind="FIELD_C-bind">
<xf:label ref="$form-resources/FIELD_C/label"/>
<xf:hint ref="$form-resources/FIELD_C/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
</xh:tr>
</fr:grid>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
</xh:html>
I do reproduce this, and this appears to be an oversight. Control data is grouped to optimize the output size, but I now see that that can cause problems!
I am not sure that it is possible to infer the order properly given the current structure. I added an issue about this.

Orbeon get documentId

I was interested in getting the documentId when submitting a form and link it to an user (i.e. by the email that is on a mandatory field of the form). The idea is to also call a webservice and send both fields to have this relationship. For now, I want to see this value in a field.
First of all, I have found that I can achieve this using xxforms:instance('fr-parameters-instance')/document but I have not success.
After this, I see here that now (I am using Orbeon 4.9) is changed to fr:document-id() but seems that I am still not able to see the document id in a simple field of the form. Bassically, something like:
<xf:action ev:event="xforms-submit">
<xf:setvalue ref="instance('fr-form-instance')/somefield" value="fr:document-id()"/>
</xf:action>
Simple example created with Form Builder:
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:exf="http://www.exforms.org/exf/1-0"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder">
<xh:head>
<xh:title>Send OrbeonID</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<!-- Main instance -->
<xf:instance id="fr-form-instance" xxf:exclude-result-prefixes="#all">
<form>
<section-1>
<control-1/>
</section-1>
</form>
</xf:instance>
<!-- Bindings -->
<xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
<xf:bind id="section-1-bind" name="section-1" ref="section-1">
<xf:bind id="control-1-bind" name="control-1" ref="control-1"/>
</xf:bind>
</xf:bind>
<!-- Metadata -->
<xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
<metadata>
<application-name>Biit</application-name>
<form-name>SendOrbeonID</form-name>
<title xml:lang="en">Send OrbeonID</title>
<description xml:lang="en"/>
<singleton>false</singleton>
</metadata>
</xf:instance>
<!-- Attachments -->
<xf:instance id="fr-form-attachments" xxf:exclude-result-prefixes="#all">
<attachments>
<css mediatype="text/css" filename="" size=""/>
<pdf mediatype="application/pdf" filename="" size=""/>
</attachments>
</xf:instance>
<!-- All form resources -->
<!-- Don't make readonly by default in case a service modifies the resources -->
<xf:instance id="fr-form-resources" xxf:readonly="false" xxf:exclude-result-prefixes="#all">
<resources>
<resource xml:lang="en">
<section-1>
<label>Untitled Section</label>
</section-1>
<control-1>
<label>Write something:</label>
<hint/>
<alert/>
</control-1>
</resource>
</resources>
</xf:instance>
<!-- Utility instances for services -->
<xf:instance id="fr-service-request-instance" xxf:exclude-result-prefixes="#all">
<request/>
</xf:instance>
<xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
<response/>
</xf:instance>
<!-- Form is sent -->
<xf:action ev:event="xforms-submit">
<xf:setvalue ref="instance('fr-form-instance')/section-1/control-1" value="fr:document-id()"/>
</xf:action>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:p="http://www.orbeon.com/oxf/pipeline">
<fr:section id="section-1-control" bind="section-1-bind">
<xf:label ref="$form-resources/section-1/label"/>
<fr:grid>
<xh:tr>
<xh:td>
<xf:input id="control-1-control" bind="control-1-bind">
<xf:label ref="$form-resources/control-1/label"/>
<xf:hint ref="$form-resources/control-1/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
<xh:td/>
</xh:tr>
</fr:grid>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
</xh:html>
Theorically, If I fill up the input field and press the submit or save button, the field must be updated with the document id. But I am not able to see any value.
The good news is that the document id is already sent as a URL parameter by default. The URL parameter name is document. See also the relevant documentation.
At the end the way I have found to send the document Id is changing the behaviour of the buttons in Orbeon.
In the save as draft button:
<property as="xs:string" name="oxf.fr.detail.process.save-draft.*.*">
save
then send("oxf.fr.detail.save-draft.success")
then success-message("save-draft-success")
recover error-message("database-error")
</property>
And define the send action to somewhere outside of Orbeon:
<property as="xs:boolean" name="oxf.fr.detail.new.accept-post.*.*" value="true" />
<property as="xs:string" name="oxf.fr.detail.save-draft.success.uri.*.*" value="http://localhost:8080/get-id.jsp?document={xxf:instance('fr-parameters-instance')/document}"/>
<property as="xs:string" name="oxf.fr.detail.save-draft.success.method.*.*" value="post"/>
The JSP page get-id.jsp now is executed each time that the user save the draft of the form, but the browser is not redirected to the JSP page.
Changing to use a webservice or other action must be easy.
When you set your form builder controls calculated value to
xxf:instance('fr-parameters-instance')/document
you can get the document id.

Managing repeatable sections through events with orbeon

I found a few questions related to my problem (Orbeon index of repeat in repeatable section, Orbeon relevant properties and Orbeon nested repeats), but I couldn't get any of them to work properly.
I define a repeatable section with a couple of questions inside and a some relevant rules. I also define some events to manage the visibility of the questions. The problem appears when I create several repeated groups. When I select one of the answers, the relevant rules and the events are launched for all the questions with the same xpath route.
So, my question is: Is there a way to manage the same events ans the same relevant rules for repeatable sections?. That is, could I define some kind of dynamic route based on the index of the section that the user is selecting at the moment and use it in the relevant rules and the events?
The complete code used for the example is below:
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:exf="http://www.exforms.org/exf/1-0"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude">
<xh:head>
<xh:meta content="text/html; charset=UTF-8" http-equiv="Content-Type"/>
<xh:title>Test_repeatable</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<xf:instance xxf:readonly="true" id="fr-form-metadata" xxf:exclude-result-prefixes="#all">
<metadata>
<application-name>Test_app</application-name>
<form-name>Test_repeatable_v1</form-name>
<title xml:lang="en">Test_repeatable</title>
<description xml:lang="en">Description of the form.</description>
<singleton>false</singleton>
</metadata>
</xf:instance>
<xf:instance id="fr-form-instance">
<form>
<Category>
<Group>
<Group-iterator>
<Question/>
<Question2/>
<Question3/>
</Group-iterator>
</Group>
</Category>
</form>
</xf:instance>
<xf:bind id="fr-form-binds" ref="instance('fr-form-instance')">
<xf:bind id="Category-bind" name="Category" ref="/form/Category">
<xf:bind id="Group-bind" name="Group" ref="/form/Category/Group">
<xf:bind id="Group-iterator-bind" name="Group-iterator"
ref="/form/Category/Group/Group-iterator">
<xf:bind id="Question-bind" name="Question" ref="Question" required="true()"/>
<xf:bind id="Question2-bind"
name="Question2"
readonly="false"
ref="Question2"
relevant="/form/Category/Group/Group-iterator/Question='Answer'"
required="true()"/>
<xf:bind id="Question3-bind"
name="Question3"
readonly="false"
ref="Question3"
relevant="/form/Category/Group/Group-iterator/Question='Answer2' or instance('visible')/Group/Group-iterator/Question2 != 'false' "
required="true()"/>
</xf:bind>
</xf:bind>
</xf:bind>
</xf:bind>
<xf:instance id="fr-form-attachments">
<attachments>
<css filename="" mediatype="text/css" size=""/>
<pdf filename="" mediatype="application/pdf" size=""/>
</attachments>
</xf:instance>
<xf:instance id="fr-form-resources" xxf:readonly="false">
<resources>
<resource xml:lang="en">
<Category>
<label>Category</label>
<hint/>
<alert/>
<Group>
<label>Group</label>
<hint/>
<alert/>
<Question>
<label>Question</label>
<hint/>
<alert/>
<item>
<label>Answer</label>
<hint/>
<value>Answer</value>
</item>
<item>
<label>Answer2</label>
<hint/>
<value>Answer2</value>
</item>
</Question>
<Question2>
<label>Question2</label>
<hint/>
<alert/>
</Question2>
<Question3>
<label>Question3</label>
<hint/>
<alert/>
</Question3>
</Group>
</Category>
</resource>
</resources>
</xf:instance>
<xf:instance id="fr-service-request-instance" xxf:exclude-result-prefixes="#all">
<request/>
</xf:instance>
<xf:instance id="fr-service-response-instance" xxf:exclude-result-prefixes="#all">
<response/>
</xf:instance>
<xf:instance xxf:readonly="true" id="Group-template">
<Group-iterator>
<Question/>
<Question2/>
<Question3/>
</Group-iterator>
</xf:instance>
<!-- Keep track of visible/hidden status -->
<xf:instance id="visible">
<visible>
<Category>0</Category>
<Group>
<Group-iterator>
<Question>false</Question>
<Question2>false</Question2>
<Question3>false</Question3>
</Group-iterator>
</Group>
</visible>
</xf:instance>
<!-- Change the visibility status for 'Question'. -->
<xf:setvalue ev:event="xforms-enabled" observer="Question-control"
ref="instance('visible')/Group/Group-iterator/Question"
value="'true'"/>
<xf:setvalue ev:event="xforms-disabled" observer="Question-control"
ref="instance('visible')/Group/Group-iterator/Question"
value="'false'"/>
<!-- Update category showed elements count for 'Question'. -->
<xf:setvalue ev:event="xforms-enabled" observer="Question-control"
ref="instance('visible')/Category"
value="instance('visible')/Category + 1"/>
<xf:setvalue ev:event="xforms-disabled" observer="Question-control"
ref="instance('visible')/Category"
value="instance('visible')/Category - 1"/>
<!-- Change the visibility status for 'Question2'. -->
<xf:setvalue ev:event="xforms-enabled" observer="Question2-control"
ref="instance('visible')/Group/Group-iterator/Question2"
value="'true'"/>
<xf:setvalue ev:event="xforms-disabled" observer="Question2-control"
ref="instance('visible')/Group/Group-iterator/Question2"
value="'false'"/>
<!-- Update category showed elements count for 'Question2'. -->
<xf:setvalue ev:event="xforms-enabled" observer="Question2-control"
ref="instance('visible')/Category"
value="instance('visible')/Category + 1"/>
<xf:setvalue ev:event="xforms-disabled" observer="Question2-control"
ref="instance('visible')/Category"
value="instance('visible')/Category - 1"/>
<!-- Change the visibility status for 'Question3'. -->
<xf:setvalue ev:event="xforms-enabled" observer="Question3-control"
ref="instance('visible')/Group/Group-iterator/Question3"
value="'true'"/>
<xf:setvalue ev:event="xforms-disabled" observer="Question3-control"
ref="instance('visible')/Group/Group-iterator/Question3"
value="'false'"/>
<!-- Update category showed elements count for 'Question3'. -->
<xf:setvalue ev:event="xforms-enabled" observer="Question3-control"
ref="instance('visible')/Category"
value="instance('visible')/Category + 1"/>
<xf:setvalue ev:event="xforms-disabled" observer="Question3-control"
ref="instance('visible')/Category"
value="instance('visible')/Category - 1"/>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:p="http://www.orbeon.com/oxf/pipeline"
xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel">
<fr:section bind="Category-bind"
id="Category-control">
<xf:label mediatype="text/html"
ref="instance('fr-form-resources')/resource/Category/label"/>
<xf:hint ref="instance('fr-form-resources')/resource/Category/hint"/>
<xf:alert ref="instance('fr-form-resources')/resource/Category/alert"/>
<fr:section bind="Group-bind"
id="Group-control"
max="100"
min="1"
repeat="content"
template="instance('Group-template')">
<xf:label mediatype="text/html"
ref="instance('fr-form-resources')/resource/Category/Group/label"/>
<xf:hint ref="instance('fr-form-resources')/resource/Category/Group/hint"/>
<xf:alert ref="instance('fr-form-resources')/resource/Category/Group/alert"/>
<xh:tr>
<xh:td>
<xf:select1 appearance="full" bind="Question-bind"
id="Question-control">
<xf:label mediatype="text/html"
ref="instance('fr-form-resources')/resource/Category/Group/Question/label"/>
<xf:hint ref="instance('fr-form-resources')/resource/Category/Group/Question/hint"/>
<xf:alert ref="instance('fr-form-resources')/resource/Category/Group/Question/alert"/>
<xf:itemset
ref="instance('fr-form-resources')/resource/Category/Group/Question/item">
<xf:label ref="label"/>
<xf:value ref="value"/>
<xf:hint ref="hint"/>
</xf:itemset>
</xf:select1>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:input bind="Question2-bind"
id="Question2-control">
<xf:label mediatype="text/html"
ref="instance('fr-form-resources')/resource/Category/Group/Question2/label"/>
<xf:hint ref="instance('fr-form-resources')/resource/Category/Group/Question2/hint"/>
<xf:alert ref="instance('fr-form-resources')/resource/Category/Group/Question2/alert"/>
</xf:input>
</xh:td>
</xh:tr>
<xh:tr>
<xh:td>
<xf:input bind="Question3-bind"
id="Question3-control">
<xf:label mediatype="text/html"
ref="instance('fr-form-resources')/resource/Category/Group/Question3/label"/>
<xf:hint ref="instance('fr-form-resources')/resource/Category/Group/Question3/hint"/>
<xf:alert ref="instance('fr-form-resources')/resource/Category/Group/Question3/alert"/>
</xf:input>
</xh:td>
</xh:tr>
</fr:section>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
</xh:html>
EDIT: A little explanation of the code above.
This example has two sections, one normal and inside of it one repeatable.
Inside the repeatable section there are three questions. The first question has two answers. When I select the first answer the form runner must show the questions two and three. When the second answer is selected the runner must show only the third question. This works correctly if I only have one repeatable section.
The problem appears when I create a new repeatable section. If I select the answer one of the first question, the following questions are shown at the same time in both repeatable groups. The same when I select answer two.
So the question is: Is there a way to tell the Orbeon runner that it must apply the relevant rules only to the repeatable group where the event happens?
EDIT 2: Ok, your solution is working perfect in the case of 'Question2'.
The problem comes with Question 3. If you check the code for Question3 you can see that I try to access also another instance:
relevant="$Question='Answer2' or instance('visible')/Group/Group-iterator/Question2 != 'false' "
The 'visible' instance is not related with any control or bind, is only used for storing an internal value for the questions and is updated using xforms events, as you can see in the code below:
<xf:setvalue ev:event="xforms-enabled"
observer="Question2-control"
ref="instance('visible')/Group/Group-iterator/Question2"
value="'true'"/>
Thus, my new question is: Is there a way to store different values for different iterations of a repeatable section in a static instance and accessing them using a dynamic path (like in your first response with the $)?
If in the xf:bind for Question2 you want to refer to the value of Question in the same iteration, then just use $Question. In fact, as a rule of thumb, you can always refer to the value of another control gaga as $gaga, and trust that the right thing will happen. (At least it will in most cases.) So, your xf:bind for Question2 will become:
<xf:bind id="Question2-bind" name="Question2"
readonly="false" ref="Question2"
relevant="$Question='Answer'"
required="true()"/>

Why is it that using xxforms-value-changed makes my hidden controls relevant?

I want an xforms:insert to occur following a hidden value change. I've set up an instance (temp-instance) to hold the value I want to observe for an xxforms-value-changed event. The event actions an insert into the destination-instance.
Also on the form I have a 'hidden' control with relevance set to false(). Subsequent to the insert occurring the relevance flag is ignored. This doesn't appear to occur with other actions being triggered (such as an xforms:setvalue).
Is this a bug?
See FR example below which updates the temp-instance with the content of the 'input' control.
<xh:html xmlns:xh="http://www.w3.org/1999/xhtml" xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xi="http://www.w3.org/2001/XInclude"
xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:exf="http://www.exforms.org/exf/1-0"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:saxon="http://saxon.sf.net/"
xmlns:sql="http://orbeon.org/oxf/xml/sql"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder">
<xh:head>
<xh:title>Untitled Form</xh:title>
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<!-- Main instance -->
<xf:instance id="fr-form-instance">
<form>
<section-1>
<input/>
<hidden>Output</hidden>
</section-1>
</form>
</xf:instance>
<!-- Temporary instance -->
<xf:instance id="temp-instance">
<temp>
<copy/>
</temp>
</xf:instance>
<!-- Template instance -->
<xf:instance id="template-instance">
<template>
<extra/>
</template>
</xf:instance>
<!-- Destination instance -->
<xf:instance id="destination-instance">
<destination/>
</xf:instance>
<!-- Bindings -->
<xf:bind xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel" id="fr-form-binds"
ref="instance('fr-form-instance')">
<xf:bind id="section-1-bind" name="section-1" ref="section-1">
<xf:bind id="input-bind" name="input" ref="input"/>
<xf:bind id="hidden-bind" ref="hidden" name="hidden" relevant="false()"/>
</xf:bind>
</xf:bind>
<xf:bind xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel" id="temp-binds"
ref="instance('temp-instance')">
<xf:bind id="copy-bind" name="copy" ref="copy" calculate="$input"/>
</xf:bind>
<!-- Metadata -->
<xf:instance xxf:readonly="true" id="fr-form-metadata">
<metadata>
<application-name>test</application-name>
<form-name>example</form-name>
<title xml:lang="en">Untitled Form</title>
<description xml:lang="en"/>
</metadata>
</xf:instance>
<!-- All form resources -->
<!-- Don't make readonly by default in case a service modifies the resources -->
<xf:instance id="fr-form-resources" xxf:readonly="false">
<resources>
<resource xml:lang="en">
<section-1>
<label>Section</label>
</section-1>
<input>
<label>Input</label>
<hint/>
</input>
<hidden>
<label>Hidden</label>
<hint/>
</hidden>
</resource>
</resources>
</xf:instance>
<xf:action id="insert-extra-binding">
<xf:action ev:event="xxforms-value-changed" ev:observer="temp-instance" if="true()">
<xf:insert context="instance('destination-instance')"
origin="instance('template-instance')"/>
</xf:action>
</xf:action>
</xf:model>
</xh:head>
<xh:body>
<fr:view>
<fr:body xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:dataModel="java:org.orbeon.oxf.fb.DataModel"
xmlns:oxf="http://www.orbeon.com/oxf/processors"
xmlns:p="http://www.orbeon.com/oxf/pipeline">
<fr:section id="section-1-control" bind="section-1-bind">
<xf:label ref="$form-resources/section-1/label"/>
<fr:grid>
<xh:tr>
<xh:td>
<xf:input id="input-control" bind="input-bind">
<xf:label ref="$form-resources/input/label"/>
<xf:hint ref="$form-resources/input/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
<xh:td>
<xf:output id="hidden-control" bind="hidden-bind">
<xf:label ref="$form-resources/hidden/label"/>
<xf:hint ref="$form-resources/hidden/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:output>
</xh:td>
</xh:tr>
</fr:grid>
</fr:section>
</fr:body>
</fr:view>
</xh:body>
I just tried your example and I do see that it seems to behave a bit curiously!
I reproduce this with a simpler example:
<xh:html
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xh="http://www.w3.org/1999/xhtml"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms">
<xh:head>
<xf:model>
<xf:instance id="instance">
<hidden>I am supposed to be hidden!</hidden>
</xf:instance>
<xf:bind ref="instance()" relevant="false()"/>
<xf:instance id="copy-instance">
<copy/>
</xf:instance>
<xf:bind ref="instance('copy-instance')" calculate="42"/>
<xf:instance id="destination-instance">
<destination/>
</xf:instance>
<xf:insert
event="xxforms-value-changed"
observer="copy-instance"
context="instance('destination-instance')"
origin="xf:element('foo')"/>
</xf:model>
</xh:head>
<xh:body>
<xf:output ref="instance()"/>
</xh:body>
</xh:html>
I added an issue:
https://github.com/orbeon/orbeon-forms/issues/1568

Resources