Dynamic elements changes in current version of Orbeon? - orbeon

I was wondering how to use a dynamic elements in Orbeon. In the sandbox of Orbeon exists an example called dynamic-dropdown (http://localhost:8080/orbeon/xforms-sandbox/sample/dynamic-dropdown).
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms">
<head>
<title>Dynamic dropdown depending on checkboxes</title>
<xf:model>
<xf:instance id="selected-values" xmlns="">
<instance>
<pets/>
<favorite/>
</instance>
</xf:instance>
<xf:instance id="pets" xmlns="">
<root>
<item name="Cat" value="cat"/>
<item name="Dog" value="dog"/>
<item name="Fish" value="fish"/>
<item name="Cobra" value="cobra"/>
</root>
</xf:instance>
</xf:model>
<style type="text/css">
.xforms-label { display: block; font-weight: bold }
</style>
</head>
<body>
<xf:select ref="pets" appearance="full">
<xf:label>Please list all your pets:</xf:label>
<xf:itemset ref="instance('pets')/item">
<xf:label ref="#name"/>
<xf:value ref="#value"/>
</xf:itemset>
</xf:select>
<br/>
<xf:select1 ref="favorite">
<xf:label>Select your favorite pet:</xf:label>
<xf:itemset>
<xf:label/>
<xf:value/>
</xf:itemset>
<xf:itemset ref="instance('pets')/item[#value = xxf:split(context()/../pets)]">
<xf:label ref="#name"/>
<xf:value ref="#value"/>
</xf:itemset>
</xf:select1>
</body>
</html>
I have tested in Orbeon 4.8 and 4.9 and does nothing. By nothing, I refer that the dropdown list does not fill up with the selected elements.
I can test it also in an "open" sandbox (http://www.argonauta.org/orbeon/xforms-sandbox/sample/dynamic-dropdown) and here is working fine. But I have no idea which version is (maybe 4.3).
The question: is the example not valid in the current version of Orbeon? is it a bug?
If the example is not valid, what modification must be done?

Ok, Seems that if you change line:
<xf:itemset ref="instance('pets')/item[#value = xxf:split(context()/../pets)]">
To
<xf:itemset ref="instance('pets')/item[#value = xxf:split(context()/pets)]">
The example works in version 4.9 of Orbeon.

Related

New component that uses autocomplete

I'm trying to create a new component that pretty much works as a pre-configured autocomplete.
The XBL components documentation is very brief, so I adapted as I could and reached this result:
<xbl:xbl xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:example="http://example.ro/xbl">
<xbl:binding
id="example-judet"
element="example|judet"
xxbl:mode="lhha binding value">
<metadata xmlns="http://orbeon.org/oxf/xml/form-builder">
<display-name lang="ro">Judeţ</display-name>
<icon lang="ro">
<small-icon>/forms/orbeon/builder/images/listbox.png</small-icon>
<large-icon>/forms/orbeon/builder/images/listbox.png</large-icon>
</icon>
<templates>
<bind required="true()"/>
<view>
<fr:autocomplete
ref="xxf:binding('example-judet')"
labelref="#label"
resource="http://localhost/counties?search={$fr-search-value}">
<xf:label>Judeţ</xf:label>
<xf:hint/>
<xf:help/>
<xf:alert>Câmp obligatoriu</xf:alert>
<xf:itemset ref="item">
<xf:label ref="label"/>
<xf:value ref="value"/>
</xf:itemset>
</fr:autocomplete>
</view>
</templates>
</metadata>
</xbl:binding>
There are 2 problems:
The selector is not working anymore - it's not querying the service on value changes
The alert and help texts work, but they do not show up in the builder's "Control settings" dialog in the appropriate tabs
Any idea what I'm doing wrong?

Validating data in Orbeon XBL component

I want to create a custom XBL component for Orbeon Form Builder that would contain an input text and validate it.
I've managed to create the component and add it to the Form Builder sidebar, but I can't figure out how to do the validation.
The validation I'm looking to do is kind of complex, it's similar to a credit card, some digits have special significance and then there's a checksum that needs to be computed and validated.
What I have so far is this:
<xbl:xbl xmlns:xf="http://www.w3.org/2002/xforms"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder"
xmlns:my="http://example.com/xbl">
<xbl:binding element="my|component" id="my-component" xxbl:mode="lhha binding value">
<metadata xmlns="http://orbeon.org/oxf/xml/form-builder">
<display-name lang="en">Component</display-name>
<icon lang="en">
<small-icon>/forms/orbeon/builder/images/input.png</small-icon>
<large-icon>/forms/orbeon/builder/images/input.png</large-icon>
</icon>
<templates>
<view>
<xf:input id="" ref="" xmlns="">
<xf:label ref=""/>
<xf:hint ref=""/>
<xf:help ref=""/>
<xf:alert ref=""/>
</xf:input>
</view>
</templates>
</metadata>
</xbl:binding>
</xbl:xbl>
You can place a validation template in the metadata, at the same level as <view>, but using <bind>. For example:
<bind
type="xf:integer"
constraint="...some XPath expression here..."/>
You could omit the xf:integer type if the value is otherwise validated by the constraint.
With constraint, you should be able to validate your checksum.
If part of your value follows the same rules as credit cards, you could use the standard is-card-number() function as a helper.

eXist-db XForms POST submission instance update

I made a simple test form for post request testig.
My simple goal is: send POST request with 2 parameters, store server response in the instance (server just sends recieved parameters back to form, untouched)
<xf:model>
<xf:instance id="request" xmlns="">
<data>
<arg1>param1</arg1>
<arg2>param2</arg2>
</data>
</xf:instance>
<xf:instance id="response" xmlns="">
<null/>
</xf:instance>
<xf:submission id="post-instance"
method="put"
replace="all"
instance="response"
resource="adderPost.xq"
ref="instance('request')"
serialization="application/xml"
mediatype="application/xml"
includenamespaceprefixes=""
>
</xf:submission>
</xf:model>
</head>
<body>
<h1>XForm interaction with XQuery</h1>
<xf:input ref="instance('request')/arg1" incremental="true">
<xf:label>Arg1:</xf:label>
</xf:input>
<br/>
<xf:input ref="instance('request')/arg2" incremental="true">
<xf:label>Arg2:</xf:label>
</xf:input>
<br/>
<xf:output ref="instance('response')/result">
<xf:label> Response:</xf:label>
</xf:output>
<br/>
<xf:submit submission="post-instance">
<xf:label>Post</xf:label>
</xf:submit>
<p id="status"></p>
</body>
if I use parameter replace="all", as it shown in code above, server returns answer:
<?xml version="1.0" encoding="UTF-8"?>
<result>
<arg1>param1</arg1>
<arg2>param2</arg2>
</result>
but, if I use parameter
replace="instance"
instance="response"
this one occurs:
throw 'allowScriptTagRemoting is false.';
(function(){
var r=window.dwr._[0];
//#DWR-INSERT
//#DWR-REPLY
r.handleCallback("2","0",[{bubbles:true,cancelable:false,contextInfo:{"resource-uri":"http://10.40.171.50:8080/exist/apps/RBS_path/adderPost.xq",
"response-headers":[null /* No converter found for 'net.sf.saxon.dom.NodeWrapper' */,null /* No converter found for 'net.sf.saxon.dom.NodeWrapper' */,null /* No converter found for 'net.sf.saxon.dom.NodeWrapper' */,null /* No converter found for 'net.sf.saxon.dom.NodeWrapper' */,null /* No converter found for 'net.sf.saxon.dom.NodeWrapper' */],
targetId:"post-instance",targetName:"submission",
"response-reason-phrase":"OK",
"response-status-code":200.0},currentTarget:null,eventPhase:1,
propertyNames:["resource-uri","response-headers","targetId","targetName","response-reason-phrase",
"response-status-code"],target:null,timeStamp:1437294248749,
type:"xforms-submit-done"}]);
})();
Response Headers:
Content-Length:935
Content-Type:text/javascript; charset=utf-8
Date:Sun, 19 Jul 2015 08:24:08 GMT
Server:Jetty(8.1.9.v20130131)
If you want to replace an instance replace="instance" is the way to go, by using replace="all" you will replace the whole page. Also I noticed you use method="put", if you want to POST you should use method="post".
See http://pastebin.ubuntu.com/11908113/ (xforms) and http://pastebin.ubuntu.com/11908115/ (xquery) for a working example.

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?
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.

Passing parameters to XBL in Orbeon

I've created these two simple files , view.xhtml :
<html xmlns="http://www.w3.org/1999/xhtml"
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:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:ev="http://www.w3.org/2001/xml-events"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms">
<head>
<title>Test</title>
<xf:model>
<!-- Instance that contains all the books -->
<xf:instance id="people-instance">
<people xmlns="">
<person>
<test/>
</person>
</people>
</xf:instance>
<xf:bind id="test-bind" name="test" ref="person/test"/>
</xf:model>
</head>
<body>
<xf:input id="test-control" bind="test-bind">
<xf:label>THIS</xf:label>
</xf:input>
<fr:my-name test="'test'">
</fr:my-name>
</body>
And my-name.xbl :
<xbl:xbl 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:ev="http://www.w3.org/2001/xml-events"
xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
xmlns:xbl="http://www.w3.org/ns/xbl"
xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
xmlns:fb="http://orbeon.org/oxf/xml/form-builder">
<xbl:binding element="fr|my-name" id="fr-my-name" xxbl:mode="lhha binding value">
<metadata xmlns="http://orbeon.org/oxf/xml/form-builder" xmlns:xf="http://www.w3.org/2002/xforms">
<templates>
<view>
<fr:my-name id="" appearance="minimal" xmlns="" test="" >
</fr:my-name>
</view>
</templates>
<xf:input ref="#test">
<xf:label lang="en">Resource URI</xf:label>
</xf:input>
</metadata>
<xbl:template>
<!-- Local model and instance -->
<xf:var name="test-avt" xbl:attr="xbl:text=test" xxbl:scope="outer"/>
<xf:var name="test" xbl:attr="xbl:text=test" >
<xf:action ev:event="xforms-enabled xforms-value-changed">
<xf:setvalue ref="instance('test')" value="$test"/>
</xf:action>
<xxf:sequence value="xxf:evaluate-avt($test-avt)" xxbl:scope="outer"/>
</xf:var>
<xf:model>
<xf:instance id="test"><value/></xf:instance>
<xf:instance><value/></xf:instance>
<xf:submission id="save-submission" ref="instance('test')"
action="/exist/rest/db/orbeon/my-name/person.xml"
method="put" replace="none">
<xf:message ev:event="xforms-submit-error" level="modal">An error occurred while saving!</xf:message>
</xf:submission>
</xf:model>
<xf:input class="xforms-disabled" ref="xxf:instance('people-instance')//*[name() = saxon:evaluate($test)]" >
<xf:label>Your name</xf:label>
<xf:send ev:event="xforms-value-changed" submission="save-submission"/>
</xf:input>
</xbl:template>
</xbl:binding>
Now I would like pass parameters from my view.xhtml to XBL so when user inserts something in xf:input id='test-control' it would cause that the text will be saved in database.
The problem is, instead of what user actually inserted in my database I have :
<value>'test'</value>
instead of expected, f.e. if I insert 123
<value>123</value>
Anyone has any idea why my code doesn't work and how to fix this ?
Here is an example which works. I put both files together to make it easier to try.
A few things I changed:
If your test attribute is in fact an AVT, it shouldn't have quotes around it. So you have for example test="foo{42}" which evaluates to foo42, which, if I understand well, is the name of the XML element you want to observe.
You probably don't want saxon:evaluate($test): the AVT is already evaluated and the result available in the variable $test. There is no point evaluating the result as an XPath expression again.
The 2nd var must not have xbl:attr="xbl:text=test"
Optional: I used xxf:binding-context('fr-my-name')/root() instead of xxf:instance(), but xxf:instance() will work too (although its usage is not recommended).
Optional: I moved the XBL model under xbl:implementation. It makes it clearer that this is not dependent on the template.

Resources