We are developing an app with xforms (with XSLTForms client) and BaseX, to manage historical entities (actors) and conduct network analysis. In one of our forms, we fill the relations between an actor and his relatives, and we'd like, when submitting the form, to create and submit a pre-filled instance for each relative…
…but we have issues with the multiple submissions.
First, we initiate the loop with a trigger, while there is more relation than the value of instance('iterate')we submit the instance('newEntity') ; and when all the relations have been sent, we submit the main form.
Then we have the submission for the "new entities". Nothing special here, when the submit is done, we set the value of relation/@ref corresponding to the last submission thanks to the response of the server, then we add "+1" to the instance('iterate')for the loop.
Everything is working great except that before each submission of instance('newEntity'), we have a submission error with an error message : "submission-in-progress".
In fact with this example, and I don't know why, we have 5 submissions instead of 3 :
2 for the relation 'Elisa Doe' (the first fails, the second is OK)
2 for the relation 'Richard Doe' (the first fails, the second is OK)
1 for John Doe (the "main" form)
We don't know how to avoid that and we are asking for some help, if someone has an idea ?
Below are the two complete files.
The form :
<htmlxmlns="http://www.w3.org/1999/xhtml"xmlns:xf="http://www.w3.org/2002/xforms"xmlns:ev="http://www.w3.org/2001/xml-events"><head><title>Submission</title><xf:model><xf:instanceid="entity"><entityxmlns=""><name>John Doe</name><age>35</age><address>North Cap</address><relations><relationref=""type="sibling">Elisa Doe</relation><relationref=""type="parent">Richard Doe</relation></relations></entity></xf:instance><xf:instanceid="newEntity"><entityxmlns=""><name/><age/><address/><relations><relationref=""type=""/></relations></entity></xf:instance><xf:instanceid="iterate"><iteratexmlns=""/></xf:instance><xf:submissionref="instance('entity')"id="submitEntity"resource="/test/form/put"method="put"replace="none"><xf:actionev:event="xforms-submit-done"><xf:messagelevel="modal">
OK !
Status : <xf:outputvalue="event('response-status-code')"/>;
URI : <xf:outputvalue="event('resource-uri')"/>;
Headers : <xf:outputvalue="event('response-headers')"/>;
Reason : <xf:outputvalue="event('response-reason-phrase')"/>;
Body : <xf:outputvalue="event('response-body')"/>.
</xf:message></xf:action><xf:actionev:event="xforms-submit-error"><xf:messagelevel="modal">
Error : <xf:outputvalue="event('error-type')"/>;
Status : <xf:outputvalue="event('response-status-code')"/>;
URI : <xf:outputvalue="event('resource-uri')"/>;
Headers : <xf:outputvalue="event('response-headers')"/>;
Reason : <xf:outputvalue="event('response-reason-phrase')"/>
Body : <xf:outputvalue="event('response-body')"/>.
</xf:message></xf:action></xf:submission><xf:submissionref="instance('newEntity')"id="submitNewEntity"resource="/test/form/put"method="put"replace="none"><xf:actionev:event="xforms-submit-done"><xf:messagelevel="modal">
OK
Status : <xf:outputvalue="event('response-status-code')"/>;
URI : <xf:outputvalue="event('resource-uri')"/>;
Headers : <xf:outputvalue="event('response-headers')"/>;
Reason : <xf:outputvalue="event('response-reason-phrase')"/>;
Body : <xf:outputvalue="event('response-body')"/>.
</xf:message><xf:setvaluevalue="event('response-body')//*:id"ref="instance('entity')//relation[position() = instance('iterate')]/@ref"/><xf:setvalueref="instance('iterate')"value="instance('iterate') + 1"/></xf:action><xf:actionev:event="xforms-submit-error"><xf:messagelevel="modal">
Error : <xf:outputvalue="event('error-type')"/>;
Status : <xf:outputvalue="event('response-status-code')"/>;
URI : <xf:outputvalue="event('resource-uri')"/>;
Headers : <xf:outputvalue="event('response-headers')"/>;
Reason : <xf:outputvalue="event('response-reason-phrase')"/>
Body : <xf:outputvalue="event('response-body')"/>.
</xf:message></xf:action></xf:submission></xf:model></head><body><xf:inputref="name"><xf:label>name : </xf:label></xf:input><br/><xf:inputref="age"><xf:label>age : </xf:label></xf:input><br/><xf:inputref="address"><xf:label>address : </xf:label></xf:input><br/><xf:repeatnodeset="relations/relation"id="repeatRelation"><xf:inputref="."><xf:label>Name : </xf:label></xf:input><xf:select1ref="@type"><xf:item><xf:label>parent</xf:label><xf:value>parent</xf:value></xf:item><xf:item><xf:label>sibling</xf:label><xf:value>sibling</xf:value></xf:item></xf:select1><xf:trigger><xf:label>X</xf:label><xf:actionev:event="DOMActivate"><xf:deleteref="."at="1"if="count(//relation) > 1"/></xf:action></xf:trigger></xf:repeat><xf:trigger><xf:label>Add relation</xf:label><xf:actionev:event="DOMActivate"><xf:insertnodeset="relations/relation"at="last()"/><xf:setvalueref="relations/relation[index('repeatRelation')] | relations/relation[index('repeatRelation')]/@*"/></xf:action></xf:trigger><br/><xf:trigger><xf:label>submit</xf:label><xf:actionev:event="DOMActivate"><xf:setvalueref="instance('iterate')"value="1"/><xf:setvalueref="instance('newEntity')/name"value="instance('entity')/relations/relation[position() = instance('iterate')]"/><xf:actionwhile="count(//relation) >= instance('iterate')"><xf:sendsubmission="submitNewEntity"/><xf:actionif="count(//relation) < instance('iterate')"><xf:sendsubmission="submitEntity"/></xf:action></xf:action></xf:action></xf:trigger></body></html>
The Xquery requests for BaseX
xqueryversion"3.0";modulenamespacetest="test";declarenamespacerest="http://exquery.org/ns/restxq";declarenamespacefile="http://expath.org/ns/file";declarenamespaceoutput="http://www.w3.org/2010/xslt-xquery-serialization";declarenamespaceweb="http://basex.org/modules/web";declarenamespaceupdate="http://basex.org/modules/update";declarenamespacedb="http://basex.org/modules/db";declarenamespacexf="http://www.w3.org/2002/xforms";declarenamespaceev="http://www.w3.org/2001/xml-events";declaredefaultelementnamespace"test";declaredefaultfunctionnamespace"test";declaredefaultcollation"http://basex.org/collation?lang=fr";declarevariable$test:xsltFormsPath:="/test/files/xsltforms/xsltforms.xsl";(:~ : this function defines a static files directory for the app : : @param $file file or unknown path : @return binary file :)declare%rest:path('test/files/{$file=.+}')functiontest:file($fileasxs:string)asitem()+{let$path:=file:base-dir()||'files/'||$filereturn(web:response-header(map{'media-type':web:content-type($path)}),file:read-binary($path))};(:~ : install db : @return create the db : : @todo create the prosopo db :)declare%rest:path("/test/install")%output:method("xml")%updatingfunctioninstall(){if(db:exists("test"))then(update:output("db 'test' already exists !"))else(update:output("db 'test' has been created"),db:create("test",<root/>,"test.xml"))};(:~ : This function returns db "test" : :)declare%rest:path("/test")%output:method("xml")functionopendb(){db:open('test')};(:~ : This function returns the entity form : :)declare%rest:path("test/form")%output:method("xml")functiontest(){fn:doc('files/submission.xml')};(:~ : This function sends entity instance to db "test" : an @xml:id is created and sent to the form as http response : @param $param content :)declare%rest:path("test/form/put")%output:method("xml")%rest:header-param("Referer","{$referer}","none")%rest:PUT("{$param}")%updatingfunctionentityPut($param,$referer){let$db:=db:open("test")returnlet$id:='person'||fn:format-integer(fn:count($db/*:root/*:entity)+1,'0000')let$param:=copy$d:=$parammodifyinsertnodeattributexml:id{$id}into$d/*return$dreturn(insertnode$paraminto$db/*:root,update:output((<rest:response><http:responsestatus="200"message=""><http:headername="Content-Language"value="fr"/><http:headername="Content-Type"value="text/plain; charset=utf-8"/></http:response></rest:response>,<result><id>{$id}</id></result>)))};
Thanks a lot for your help !!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
It is currently not possible with XSLTForms to put the same submission more than once in asynchronous mode while the previous one is not yet finished. As a workaround, I suggest you to add "mode='synchronous'" to your submission declarations.
Thank you for your feedback!
--Alain
Last edit: Alain Couthures 2019-12-24
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hi everyone
We are developing an app with xforms (with XSLTForms client) and BaseX, to manage historical entities (actors) and conduct network analysis. In one of our forms, we fill the relations between an actor and his relatives, and we'd like, when submitting the form, to create and submit a pre-filled instance for each relative…
…but we have issues with the multiple submissions.
Basically, we have 3 instances :
instance('entity')for the main forminstance('newEntity'), filled and sent successively for eachrelationininstance('entity')(for the example we just copy the name value)instance('iterate'), for looping the submissions ofinstance('newEntity')(when instance('iterate') = 1, we processrelation[position() = 1], etcAnd here is our submit process :
First, we initiate the loop with a trigger, while there is more
relationthan the value ofinstance('iterate')we submit theinstance('newEntity'); and when all the relations have been sent, we submit the main form.Then we have the submission for the "new entities". Nothing special here, when the submit is done, we set the value of
relation/@refcorresponding to the last submission thanks to the response of the server, then we add "+1" to theinstance('iterate')for the loop.And finally we are submitting the main form when all the relations have been saved
Everything is working great except that before each submission of
instance('newEntity'), we have a submission error with an error message : "submission-in-progress".In fact with this example, and I don't know why, we have 5 submissions instead of 3 :
We don't know how to avoid that and we are asking for some help, if someone has an idea ?
Below are the two complete files.
The form :
The Xquery requests for BaseX
Thanks a lot for your help !!
Hello Josselin,
It is currently not possible with XSLTForms to put the same submission more than once in asynchronous mode while the previous one is not yet finished. As a workaround, I suggest you to add "mode='synchronous'" to your submission declarations.
Thank you for your feedback!
--Alain
Last edit: Alain Couthures 2019-12-24
Hello Alain,
Thank you very much for your help, with "mode='synchronous'" it works perfectly !
I missed this feature.
Thank you again,
Josselin