Search code examples
eventsxpageslotus-noteslotus-domino

How can i invoke an event handler of control A from the control B?


I have 2 comboBoxes in my XPage. Combo A and Combo B. Combo A has an event handler onChange. When i change combo B value i want to invoke Combo A onChange event so as to execute a code that exists there and avoid duplicating it into combo B event.

So in onChange event of combo B i want to invoke onChange event of combo A.

I dont mind if i have to change combo A value. In fact i tried to do so with CSJS and SSJS but the onChange event of A did not fire although the value was changed.


Solution

  • You can do this on client side. I am using the following JS function from this answer.

    // itemId : ID of an element
    // eventName: The name of the event (change, click, etc.)
    function fireEvent(itemId, eventName) {
        var item=dojo.byId(itemId);
    
        if(item) {
            if (dojo.isIE) {
                // IE does things differently
                item.fireEvent("on"+eventName);
            }
            else { 
                // Not IE
                var event = document.createEvent("HTMLEvents");
                event.initEvent(eventName, false, true); // Last two arguments: bubbles, cancelable
                item.dispatchEvent(event);
            }
        } else {
            console.log("'"+itemId+"' does not exist!");    
            // Item does not exist! 
        }
    }
    

    However there is a tricky part for XPages. If your combo box is triggering a server-side event you should call this function at onComplete. Otherwise you can put a client-side script. For instance:

    <xp:comboBox
        id="targetComboBox"
        value="#{viewScope.TargetCombo}">
    <!-- Some select items here -->
    </xp:comboBox>
    
    <xp:comboBox
        id="comboBox1"
        value="#{viewScope.Combo1}">
        <xp:selectItem
            itemLabel="Value1.1"
            itemValue="1.1">
        </xp:selectItem>
        <xp:selectItem
            itemLabel="Value1.2"
            itemValue="1.2">
        </xp:selectItem>
        <xp:selectItem
            itemLabel="Value1.3"
            itemValue="1.3">
        </xp:selectItem>
        <xp:eventHandler
            event="onchange"
            submit="false">
            <xp:this.script>
                <xp:scriptGroup>
                    <xp:executeClientScript script="console.log('combo1 changed');"></xp:executeClientScript>
                    <xp:executeClientScript script="fireEvent('#{id:targetComboBox}', 'change')"></xp:executeClientScript>
                </xp:scriptGroup>
            </xp:this.script>
        </xp:eventHandler>
    </xp:comboBox>
    
    <xp:comboBox
        id="comboBox2"
        value="#{viewScope.Combo1}">
        <xp:selectItem
            itemLabel="Value2.1"
            itemValue="2.1">
        </xp:selectItem>
        <xp:selectItem
            itemLabel="Value2.2"
            itemValue="2.2">
        </xp:selectItem>
        <xp:selectItem
            itemLabel="Value2.3"
            itemValue="2.3">
        </xp:selectItem>
        <xp:eventHandler
            event="onchange"
            submit="true"
            refreshMode="norefresh"
            onComplete="fireEvent('#{id:targetComboBox}', 'change')">
            <xp:this.action><![CDATA[#{javascript:print("combo2 changed")}]]></xp:this.action>
            <xp:this.script>
                <xp:scriptGroup>
                    <xp:executeClientScript script="console.log('combo2 changed');"></xp:executeClientScript>
                </xp:scriptGroup>
            </xp:this.script></xp:eventHandler>
    </xp:comboBox>
    

    In this example, combo1 has its own CSJS event and combo2 has one SSJS and one CSJS event. Both are triggering the targetComboBox...