Changing default evaluation context inside an action object - orbeon

Is there any XForms object which I could use to override default evaluation context inside an action object? We have xforms:group in body part but do we have any in xforms:action? It would simplify code where I often use the same Nodeset as a base element I'm operating on
I would like to receive such code:
<xf:action ev:event="DOMActivate">
<?xf:context? ref="instance('main')/d:Content/d:Attachment[index('repeat-id')]"> <!-- ?? -->
<xf:setvalue ref="d:FileName" value="..." />
<xf:setvalue ref="d:Description" value="..." />
<xf:setvalue ref="d:MimeType" value="..." />
<xf:setvalue ref="d:Size" value="..." />
<xf:setvalue ref="d:Location" value="..." />
</?xf:context?>
</xf:action>
so I wouldn't have to repeat the whole path all over again.

The attribute you are looking for is context. As of XForms 1.1, the context attribute is only available officially on the insert and delete actions, but some implementations already support it on all actions, and it is scheduled for inclusion in XForms 2.
<xf:action ev:event="DOMActivate" context="instance('main')/d:Content/d:Attachment[index('repeat-id')]">
<xf:setvalue ref="d:FileName" value="..." />
<xf:setvalue ref="d:Description" value="..." />
<xf:setvalue ref="d:MimeType" value="..." />
<xf:setvalue ref="d:Size" value="..." />
<xf:setvalue ref="d:Location" value="..." />
</xf:action>
Note that ref is, as far as I know, not officially allowed on action.
There is a difference between ref and context as planned for the upcoming XForms 2:
context only changes the XPath evaluation context
ref usually has other effects, such as binding a control, or specifying the destination of a value (setvalue), etc.
In XForms 1.1, context on insert unfortunately also can indicate the insertion point, but XForms 2 plans to improve on that and deprecate that use of context.

Yes. you can have ref attribute to the <xforms:action>tag. And you can apply this to <xforms:trigger> and <xforms:group> tags also.
With this, you will give the context for the statements within the tag.
I have tried this which works fine.
So your code should look something like:
<xf:action ev:event="DOMActivate" ref="instance('main')/d:Content/d:Attachment[index('repeat-id')]">
<xf:setvalue ref="d:FileName" value="..." />
<xf:setvalue ref="d:Description" value="..." />
<xf:setvalue ref="d:MimeType" value="..." />
<xf:setvalue ref="d:Size" value="..." />
<xf:setvalue ref="d:Location" value="..." />
</?xf:context?>
</xf:action>

Related

xf:submission: Populate Header Value From Current Context

I'm wanting to populate the header in a xf:submission with a value from the current context. Documentation says that an xpath expression can be used but doesn't provide any examples.
I've tried using xsl:value, seen below, but that doesn't populate anything. Is that the correct syntax to populate xf:value?
<p:for-each href="#attachments" select="//attachment" root="attachments" id="post-document-pages">
<p:processor name="oxf:xforms-submission">
<p:input name="submission">
<xf:submission
method="post"
resource="http://localhost:8080/is/document/{#documentId}/page"
serialization="application/octet-stream">
<xf:header>
<xf:name>Resource-Name</xf:name>
<xf:value>
<xsl:value-of select="#filename" />
</xf:value>
</xf:header>
</xf:submission>
</p:input>
<p:input name="request" href="current()" />
<p:output name="response" ref="post-document-pages" />
</p:processor>
Inside the <xf:header>, simply use:
<xf:value value="[your XForms expression here]"/>

Orbeon disable custom submit to external webservice after submit

How can I disable a custom submit button after submit?
Below you can find my part of code to send:
<xf:trigger bind="booking-bind" id="booking">
<xf:label>
<xh:span>
<xf:output value="'Send'"/>
</xh:span>
</xf:label>
<xf:action ev:event="DOMActivate">
<xf:setvalue ref="instance('fr-form-instance')/submission_type">SendBooking</xf:setvalue>
<xf:setvalue ref="instance('fr-form-instance')/submission_extra_info">//booking[1]</xf:setvalue>
<xf:action type="xpath" xmlns:process="java:org.orbeon.oxf.fr.process.SimpleProcess">
process:runProcessByName('oxf.fr.detail.process', 'send')
</xf:action>
</xf:action>
</xf:trigger>
I am using this solution: Orbeon upgrade from 3.9 to 4.5 : Customized submit for saving forms
I see your trigger has a booking-bind bind. You could have a readonly MIP saying whether the button should be readonly. For example:
<bind id="booking-bind" readonly=". = 'sent'"/>
Then, in your action, do:
<xf:setvalue ref="xxf:bind('booking-bind')" value="'sent'"/>
This will cause the trigger to become readonly.
By the way we have an issue to tackle this better.

How to make resource language attribute dynamic in Orbeon Forms?

In my model i define an instance related to form-resources.
I want to set "xml:lang" value dynamically by a xpath expr in a variable.
I tried but the xml:lang attribute of resource element isn't evaluating the variable, but instead it recognises it as string! (xml:lang="$language")
...
<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
<xf:var name="language" value="de" as="xs:string" />
...
<xf:instance id="fr-form-resources" xxf:readonly="false">
<resources>
<!-- How "xml:lang" attribute can have dynamic value
from a variable/xpath instead of static string 'de' ? -->
<resource xml:lang="de">
<IntegerField>
<label>%translation.IntegerField%</label>
<IntegerField />
</Project>
<cancel>
<label>%translation.cancel%</label>
<hint />
</cancel>
<ok>
<label>%translation.ok%</label>
<hint />
</ok>
</resource>
</resources>
</xf:instance>
</xf:model>
Is there any way to achieve this?
Using Orbeon 4.5
Use an xf:bind for this; something like:
<xf:bind
ref="instance('fr-form-resources')/resource/#xml:lang"
calculate="$language"/>
This is the general mechanism in XForms to have something an instance automatically calculated and re-evaluated as users interact with the form.

Form Builder in 4.3 Removing setvalue and help lines

I have been using Form Builder to stage the deployment of Orbeon Forms.
Ie, I iterate form definitions between FB and Oxygen by copying the code into Form Builder -> Edit Source. Then I save and publish the form definition.
This seemed to work ok in 4.2 (ok - I would lose some comments, not ideal, but not functionality).
I'm now getting a very different situation using 4.3. Saving in Form Builder is removing actual code (not ideal). Has anyone else seen this?
For instance, my code:
<xf:action id="create-job-binding">
<!-- React to event... on control... -->
<xf:action ev:event="DOMActivate" ev:observer="save-job-control" if="true()">
<!-- Service to call -->
<xf:send submission="new-job-submission"/>
</xf:action>
<!-- Request actions -->
<xf:action ev:event="xforms-submit" ev:observer="new-job-submission">
<!-- Get reference to initial request -->
<xf:var name="request-instance-name" value="'new-job-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">
<!-- Parameters -->
<xf:var name="control-name" value="'car-id'" as="xs:string"/>
<xf:var name="path" value="/request/car-id" as="xs:string"/>
<!-- Set value -->
<xf:setvalue ref="$path" value="instance('edited-job')/job/*[name() = $control-name]"/>
</xf:action>
<xf:action class="fr-set-service-value-action">
<!-- Parameters -->
<xf:var name="control-name" value="'driver-id'" as="xs:string"/>
<xf:var name="path" value="/request/driver-id" as="xs:string"/>
<!-- Set value -->
<xf:setvalue ref="$path" value="instance('edited-job')/job/*[name() = $control-name]"/>
</xf:action>
<xf:action class="fr-set-service-value-action">
<!-- Parameters -->
<xf:var name="control-name" value="'document'" as="xs:string"/>
<xf:var name="path" value="/request/event-id" as="xs:string"/>
<!-- Set value -->
<xf:setvalue ref="$path"
value="xxf:instance('fr-parameters-instance')/*[name() = $control-name]"/>
</xf:action>
<!-- Setvalue actions will be here -->
</xf:action>
</xf:action>
<!-- Response actions -->
<xf:action ev:event="xforms-submit-done" ev:observer="new-job-submission"
context="instance('fr-service-response-instance')">
<!-- Response actions will be here -->
</xf:action>
</xf:action> `
after saving in FB becomes:
<xf:action id="create-job-binding">
<!-- React to event... on control... -->
<xf:action ev:event="DOMActivate" ev:observer="save-job-control" if="true()">
<!-- Service to call -->
<xf:send submission="new-job-submission"/>
</xf:action>
<!-- Request actions -->
<xf:action ev:event="xforms-submit" ev:observer="new-job-submission">
<!-- Get reference to initial request -->
<xf:var name="request-instance-name" value="'new-job-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="'car-id'" as="xs:string"/>
<xf:var name="path" value="/request/car-id" as="xs:string"/>
</xf:action>
<xf:action class="fr-set-service-value-action">
<xf:var name="control-name" value="'driver-id'" as="xs:string"/>
<xf:var name="path" value="/request/driver-id" as="xs:string"/>
</xf:action>
<xf:action class="fr-set-service-value-action">
<xf:var name="control-name" value="'document'" as="xs:string"/>
<xf:var name="path" value="/request/event-id" as="xs:string"/>
</xf:action>
<!-- Setvalue actions will be here -->
</xf:action>
</xf:action>
<!-- Response actions -->
<xf:action ev:event="xforms-submit-done" ev:observer="new-job-submission"
context="instance('fr-service-response-instance')">
<!-- Response actions will be here -->
</xf:action>
</xf:action>
Notice loss of the setValue commands.
Also removed xf:help references:
<xh:tr>
<xh:td colspan="2">
<xf:textarea id="pickup-address-control" bind="pickup-address-bind">
<xf:label ref="$form-resources/pickup-address/label"/>
<xf:hint ref="$form-resources/pickup-address/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:textarea>
</xh:td>
<xh:td>
<xf:input id="pickup-postcode-control" bind="pickup-postcode-bind">
<xf:label ref="$form-resources/pickup-postcode/label"/>
<xf:hint ref="$form-resources/pickup-postcode/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:input>
</xh:td>
<xh:td>
<xf:textarea id="notes-control" bind="notes-bind">
<xf:label ref="$form-resources/notes/label"/>
<xf:hint ref="$form-resources/notes/hint"/>
<xf:alert ref="$fr-resources/detail/labels/alert"/>
</xf:textarea>
</xh:td>
</xh:tr>
This appears to be intended behaviour in 4.3 Form Builder/Runner. I maybe should have done a bit more research on 4.3 before posting. Anyway:
Removal of xf:help elements on controls. These are removed if the ref points to an empty element.
Removal of setvalue commands. These are removed if the class of the action is one which is templated in ~/resources/apps/fr/components/actions.xsl (for instance fr-set-control-value-action).
My 4.2 forms didn't work following upgrade because I had edited the source to change the action settings to refer to elements not within the FB context (other instances), but had left the class tag unchanged. Removal of the class tag solved the problem.

XForms bind does not update when referenced instance data is updated

My problems is this:
I have 2 instances in my model:
<xf:instance id="Include-model">
<data>
<value type="xs:string">true</value>
</data>
</xf:instance>
this is wired up to a checkbox,
and
<xf:instance id="items-model">
<items>
<item>1</item>
<item>2</item>
<item>3</item>
</xf:instance>
and I have a bind declared as:
<xforms:bind id="items-bind" nodeset="items[instance('Include-model')/value = 'true']">
the checkbox correctly updates the Include-model, but the bind does not update to reflect this. Basically, if the checkbox is checked I need to display the items, otherwise hide them. The initial state is correct, but changes are not reflected in the bind when I check/uncheck the checkbox.
Eternal gratitude to all who can help.
You might try
<xforms:bind id="items-bind" nodeset="instance('items-model')" relevant="instance('Include-model')/value = 'true'" />
First up, I could see there are multiple issues in the code snippets you give here.
closing tag is missing here. It should look like
<xforms:instance id="items-model">
<items>
<item>1</item>
<item>2</item>
<item>3</item>
</items>
</xforms:instance>
The nodeset in the bind mentioned is for items. It should be for item. Since there is no information given whether it a code pulled from form-builder or "hand-written" code, i cannot say it is correct or not. For a "hand-written" codes the bind defnition in your case will look like this
<xforms:bind id="items-bind" nodeset="instance('items-model')/item[instance('Include-model')/value = 'true']" />
Below is the complete Xforms code you can run for this case. Try running with value as 'true' and again value as 'false' to understand how bind is working.
<xhtml:html xmlns:xhtml="http://www.w3.org/1999/xhtml"
xmlns:xxforms="http://orbeon.org/oxf/xml/xforms"
xmlns:xforms="http://www.w3.org/2002/xforms">
<xhtml:head>
<xhtml:title>Xforms</xhtml:title>
<xforms:model>
<xforms:instance id="Include-model">
<data>
<value type="xs:string">true</value>
</data>
</xforms:instance>
<xforms:instance id="items-model">
<items>
<item>1</item>
<item>2</item>
<item>3</item>
</items>
</xforms:instance>
<xforms:bind id="items-bind" nodeset="instance('items-model')/item[instance('Include-model')/value = 'true']" />
</xforms:model>
</xhtml:head>
<xhtml:body>
<table>
<tr>
<td>Bind items are
<xforms:output value="
string-join(xxforms:bind('items-bind'), ' -- ')
" />
</td>
</tr>
</table>
</xhtml:body>
</xhtml:html>

Resources