Question

I am having trouble inserting row with xbl components at a particular position. It works if I insert row at the end but if I try to insert row in the middle then xbl components init method is not called.

Here is the xhtml.

<xhtml:head>
    <xforms:model id="main" 
                  xxforms:session-heartbeat="true"
                  xxforms:show-error-dialog="false" 
                  xxforms:external-events="submit-save submit-preview submit-cancel">

        <xforms:instance id="instance">
            <root>
                <repeat>
                    <item>
                        <title/>
                    </item>
                </repeat>           
            </root>
        </xforms:instance>

        <xforms:instance id="proto-property">
            <item>
                <title/>
            </item>
        </xforms:instance>

        <xforms:bind nodeset="instance('instance')">
            <xforms:bind
                nodeset="repeat/item/title"
                required="true()" />
        </xforms:bind>

    </xforms:model>
    <xbl:xbl xmlns:xhtml="http://www.w3.org/1999/xhtml"
     xmlns:xforms="http://www.w3.org/2002/xforms"
     xmlns:xs="http://www.w3.org/2001/XMLSchema"
     xmlns:ev="http://www.w3.org/2001/xml-events"
     xmlns:xi="http://www.w3.org/2001/XInclude"
     xmlns:xxi="http://orbeon.org/oxf/xml/xinclude"
     xmlns:xxforms="http://orbeon.org/oxf/xml/xforms"
     xmlns:fr="http://orbeon.org/oxf/xml/form-runner"
     xmlns:saxon="http://saxon.sf.net/"
     xmlns:oxf="http://www.orbeon.com/oxf/processors"
     xmlns:xbl="http://www.w3.org/ns/xbl"
     xmlns:xxbl="http://orbeon.org/oxf/xml/xbl"
     xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xbl:script src="/apps/xforms-sandbox/samples/input-counted.js" />

    <xbl:binding id="fr-input-counted" element="fr|input-counted">
        <xbl:template xxbl:transform="oxf:unsafe-xslt">
            <xsl:transform version="2.0">
                <xsl:import href="oxf:/oxf/xslt/utils/xbl.xsl" />
                <xsl:template match="/*">
                    <xforms:group xbl:attr="model context ref bind" xxbl:scope="outer">

                        <xbl:content includes="xforms|label" />                             

                        <xsl:copy-of select="xxbl:parameter(., 'max')" />

                        <xxforms:script ev:event="xforms-enabled" ev:target="#observer">
                            YAHOO.xbl.fr.InputCounted.instance(this).initialize();
                        </xxforms:script>

                        <xforms:group xxbl:scope="inner">
                            <xxforms:variable name="binding" as="node()?">
                                <xxforms:sequence select="." xxbl:scope="outer"/>
                            </xxforms:variable>
                            <xforms:input id="input-counted" class="fr-input-counted" ref="$binding" incremental="true" />
                            <label class="counter-label"></label>
                        </xforms:group>
                    </xforms:group>
                </xsl:template>
            </xsl:transform>
        </xbl:template>
    </xbl:binding>

</xbl:xbl>

</xhtml:head>

<xhtml:body class="body">

    <div>
        <xforms:trigger appearance="full">
            <xforms:label>
              Add Another  
            </xforms:label>
            <xforms:insert ev:event="DOMActivate" at="1"
            nodeset="repeat/item"/>
        </xforms:trigger>
    </div>

    <xforms:repeat nodeset="repeat/item">
        <div>
            <fr:input-counted ref="title" max="10">
                <xforms:label>Node Selector </xforms:label>
            </fr:input-counted>
        </div>
    </xforms:repeat>
</xhtml:body>

Try to click on Add Another multiple times and you will see that it is not populating the size next to input box.

You can download the required js file from the following URL. (http://orbeon-forms-ops-users.24843.n4.nabble.com/Error-in-repeat-for-controls-having-relevant-td2331649.html#a2533819). It is the same error but made it simple by removing the relevant.

I am using Orbeon 3.8 and xforms.js line 3798 has the following code. If I have "at" attribute in insert it never goes inside. This is because I am trying to insert a row where a row was previously initialized.

                    if (! this.initialized) {
                        originalInit.call(this);
                        this.initialized = true;
                    }

Is this is a bug?

Thank You Binesh Gummadi

Was it helpful?

Solution

Two things:

First, make sure that the method used to initialize your object is called init() (not initialize()). This because the plumbing that gets injected when you call ORBEON.xforms.XBL.declareClass() makes sure that every time you call instance(), if an instance for the current component can't be found, one is created, and init() is being called on that object. It also ensure that init() is called just once.

Second, add xxforms-iteration-moved in addition to xforms-enabled to the events that trigger the XBL object to be initialized:

<xxforms:script ev:event="xforms-enabled xxforms-iteration-moved" ev:target="#observer">
    YAHOO.xbl.fr.InputCounted.instance(this).init();
</xxforms:script>

With those two changes, from what I can see, the component seems to get properly initialized (I am getting the 0/10 on each line after the text field).

OTHER TIPS

https://gist.github.com/768034

Here is the simplified version of the same error. When control becomes relevant after making it irrelevant init method is not called which goes back to my previous observation(xforms.js line 3798).

Steps to reproduce

  1. Observe two alerts upon page load
  2. Uncheck the check box
  3. Check the check box (observe only one alert. "initialized" alert is not displayed)

Is this the right behavior?

(This is an answer to a follow-up question posted as an answer on this page. Hem.)

Yes, this is the intended behavior, and I understand how this can be confusion. The idea of the init() method is to initialize your JavaScript object and do some initialization to the DOM. If you get an instance of your object with instance(), then this method will be called automatically for you before any other method is called on your object.

This explains why you don't see init() called when your component becomes enabled again. What you want to do here is split the code your in init() into:

  • The part that really initializes the component — which you keep in init().
  • The part that changes the appearance of your component so it shows as enabled — which you put in a new method enabled().

Then you write:

<xxforms:script ev:event="xforms-enabled">
    YAHOO.xbl.fr.InputCounted.instance(this).enabled();
</xxforms:script>

Note that you don't need to call init() explicitly; this will be done for you before any other method is called. Something similar is done in code for the fr:button.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top