Search code examples
orbeonxformsxbl

Refer to an outer instance from an XBL component in Orbeon


I am making my own component and within it I want to set value of an outer instance. For example, my main form has:

<xf:model id="fr-form-model" xxf:expose-xpath-types="true">
    <!-- Main instance -->
    <xf:instance id="fr-form-instance">
        <form>
            <section-1>
                <myControl/>
            </section-1>
        </form>
    </xf:instance>
    ...

and inside myControl.xbl I have:

<xf:setvalue
  model="fr-form-model"
  ref="instance('fr-form-instance')/form/section-1/myControl"
  value="'myValue'" /> 

but unfortunately it doesn't see fr-form-model ("Reference to non-existing model id: fr-form-model") which is understandable, because the component is encapsulated and cannot see outer elements. How can I refer to the outer instance?


Solution

  • You can write to the control binding with xxf:binding() (see also gist):

    <xh:html
            xmlns:xh="http://www.w3.org/1999/xhtml"
            xmlns:xf="http://www.w3.org/2002/xforms"
            xmlns:xxf="http://orbeon.org/oxf/xml/xforms"
            xmlns:fr="http://orbeon.org/oxf/xml/form-runner">
        <xh:head>
            <xf:model>
                <xf:instance>
                    <value/>
                </xf:instance>
            </xf:model>
            <xbl:xbl xmlns:xbl="http://www.w3.org/ns/xbl" xmlns:xxbl="http://orbeon.org/oxf/xml/xbl">
                <xbl:binding id="fr-gaga" element="fr|gaga" xxbl:mode="binding">
                    <xbl:template>
                        <xf:trigger>
                            <xf:label>Set value</xf:label>
                            <xf:setvalue event="DOMActivate" ref="xxf:binding('fr-gaga')" value="42"/>
                        </xf:trigger>
                    </xbl:template>
                </xbl:binding>
            </xbl:xbl>
        </xh:head>
        <xh:body>
            <fr:gaga ref="instance()"/>
            <xf:output value="instance()"/>
        </xh:body>
    </xh:html>
    

    Otherwise, the quick and dirty way is to use the xxf:instance() function instead. It has visibility through the boundaries of XBL components. But we don't recommend it as it breaks encapsulation.

    See also this forum answer.