Search code examples
orbeonxforms

Adding pre-processing stage into send-workflow button in Orbeon XForms Form runner


I have a form in Orbeon Form runner where I needed to add external validation before submitting with 'workflow-send'. Can we add capability to 'workflow-send' button in properties-local.xml for that?

For the record, I have also implemented a button which does the validation and does certain actions when the validation results come back. So alternatively, can we add 'workflow-send' capability to that button of mine?


Solution

  • I have done this by making some changes to the persistence-model.xml file. This kind of validation needs to be done in the persistence stage. Because, what we need was a server-side validation (accessing database etc) that was called before saving the data and obviously before workflow-send.

    I have commented out the old code snippets.

    <!-- Respond to send button activation -->
    <xforms:action ev:event="DOMActivate" ev:observer="fr-workflow-send-button">
        <xforms:send submission="validation-submission" />
        <!-- xforms:setvalue ref="instance('fr-persistence-instance')/submit-or-save-or-send">send</xforms:setvalue> 
            <xforms:dispatch name="fr-save-action" target="fr-persistence-model"> <xxforms:context 
            name="fr:check-data-valid" select="true()" /> </xforms:dispatch -->
    </xforms:action>
    
    <xforms:action ev:event="my-valid-action">
        <xforms:setvalue
            ref="instance('fr-persistence-instance')/submit-or-save-or-send">send</xforms:setvalue>
        <xforms:dispatch name="fr-save-action" target="fr-persistence-model">
            <xxforms:context name="fr:check-data-valid" select="true()" />
        </xforms:dispatch>
    </xforms:action>
    
    <xforms:instance id="validation-result">
        <dummy />
    </xforms:instance>
    
    <xforms:submission id="validation-submission"
        ref="xxforms:instance('fr-form-instance')" resource="http://localhost:8080/MyApp/OrbeonValidationServlet"
        method="post" replace="instance" instance="validation-result">
        <!-- Clear external errors just before doing external validation -->
        <xforms:delete ev:event="xforms-submit" nodeset="//@v:*" />
        <xforms:action ev:event="xforms-submit-done">
            <!-- Insert external validation results when done -->
            <xforms:insert nodeset="."
                origin="instance('validation-result')/v:data/*" />
            <!-- Show all errors on form -->
            <xforms:dispatch name="fr-visit-all" targetid="error-summary" />
            <!-- Update error summary for incremental mode -->
            <xforms:refresh />
            <xforms:dispatch name="fr-update" targetid="error-summary" />
            <xforms:dispatch name="my-valid-action" target="fr-persistence-model"
                if="count(instance('validation-result')/v:global-errors/*) 
                = 0" />
        </xforms:action>
    </xforms:submission>
    

    So basically

    • I have implemented my-valid-action and validate-submission
    • Placed validate-submission instead of workflow-send
    • Dispatch my-valid-action only if there is no error
    • Call workflow-send from my-valid-action

    The last thing was binding validation-result to a fr:error-summary in my form.

    One can try harder and make /OrbeonValidationServlet settable from properties-local.xml.