Search code examples
javascriptjqueryxmlorbeonxforms

In XForms, with Orbeon, how to update an XML instance through jQuery?


I want to perform some logic in JavaScript when users click on the span element and update current XML instance from jQuery:

(I have seen 2 similar questions online but they never got answered!)

XForms:

<xhtml:span class="buttonPlusOne" id="plusVat">+</xhtml:span>
<xf:output ref="instance('submitted_instance')/TotVATAmnt"></xf:output>
<xf:input id="changeVatTotal" ref="instance('submitted_instance')/TotVATAmnt"></xf:input>

JavaScript:

$('span.buttonPlusOne').on('click', function () {
    // do some logic and increment value for 0.01
    orbeonElId = $(this).siblings('#changeVatTotal').children('input').attr('id');
    // alert(orbeonElId) produces right id (changeVatTotal$xforms-input-1)
    // alert(newValue) produces 0.02 (for example)
    ORBEON.xforms.Document.setValue(orbeonElId, newValue);
});

I can see Orbeon posting data (Firebug), but the XML Instance does not get updated (input does not update the output - even though they share same "ref" attribute).


Solution

  • I suppose that you're mixing up the html element's id with the XForms id (id attribute) of the xf:input element.

    The Orbeon documentation shows an example: the id to use in the ORBEON.xforms.Document.setValue() function call is the id of the (server-side) XForms element. So in your example it's changeVatTotal, and not the id of the (client-side) html input element changeVatTotal$xforms-input-1. This is why there's a request showing up in firebug with no effect on the XForms instance: the server-side XForms engine doesn't find a xf:input element with the id changeVatTotal$xforms-input-1, so it doesn't know what to do with that request.

    This means, too, that you (usually) don't need to compute the id of the target element, instead you can just use the "plain" XForms id attribute value of the xf:input.

    Alternatively:

    Is it possible to handle the "plus" button completely in XForms? You could use a xforms:trigger control and include a xforms:setvalue action on the DOMActivate event:

    <xf:trigger>
        <xf:label>+</xf:label>
        <xf:setvalue
            ev:event="DOMActivate"
            ref="instance('submitted_instance')/TotVATAmnt"
            value="0.01 + instance('submitted_instance')/TotVATAmnt" />
        <.... more actions ...>
    </xf:trigger>
    

    I think this solution would be more stable than doing some of the work client-side and some server-side.