0
votes

on my XPage I have a BS accordian defined:

<div class="panel-collapse collapse in" id="collapseOne" aria-expanded="true" style="">
</div>

on an button I would like to save the state of the panel, so after a full refresh I would like to display the accordian panel in it's previous state.

So my button looks now as followed:

<xp:button
        value="Label"
        id="button1">
    <xp:eventHandler
        event="onclick"
        submit="true"
        refreshMode="complete">
        <xp:this.script><![CDATA[if ($('#collapseOne').attr('aria-expanded') == "false") {
"#{javascript:viewScope.put('accordian','collapsed')}";
}else{
"#{javascript:viewScope.put('accordian','expanded')}";
}]]></xp:this.script>
    </xp:eventHandler>
</xp:button>

Whatever state the accordian is the viewScope 'accordian' is set to 'expanded' eventhough the script identifies the correct state of the accordian.

What am I doing wrong?

Update:

I set up as suggested an RPC service but it does not work. what am I doing wrong?

<xe:jsonRpcService
                                id="rpcServiceSetState">
                            <xe:this.methods>
                                <xe:remoteMethod
                                    name="setPanelState"
                                    loaded="true"
                                    script="viewScope.put('accordian', state)">
                                    <xe:this.arguments>
                                        <xe:remoteMethodArg
                                            name="state"
                                            type="string">
                                        </xe:remoteMethodArg>
                                    </xe:this.arguments>
                                </xe:remoteMethod>
                            </xe:this.methods></xe:jsonRpcService>
                            <xp:button id="btnTriggerRPC" value="Trigger RPC Method">
        <xp:eventHandler
            event="onclick"
            submit="true" refreshMode="complete">
            <xp:this.script><![CDATA[if ($('#collapseOne').attr('aria-expanded') == "false") {
    rpcServiceSetState.setPanelState('collapsed')
}else{
    rpcServiceSetState.setPanelState('expanded')
}]]></xp:this.script>
        </xp:eventHandler>
                            </xp:button>
2
The SSJS code is always executed when the CSJS code is generated and sent to the client. That's why accordian is always set to expanded. - Sven Hasselbach
but if add an alert for the if else construction it detects the state and alerts the correct state? is there anyway to work around/solve this? - Malin
The if/else - block is executed in the browser, that's why an alert works. If you want to update the server side state you need to update it, for example with a RPC call. - Sven Hasselbach
The JSON RPC service won't help with this though, because the component tree doesn't get updated intec.co.uk/…. - Paul Stephen Withers
Hi Sven, I updated my question with suggested rpc method but I must be doing something wrong here? - Malin

2 Answers

1
votes

this code below allows me to set a viewscope via RPC service?

<xe:jsonRpcService id="jsonRpcServiceSelected"
        serviceName="rpcService" rendered="true">
        <xe:this.methods>
            <xe:remoteMethod name="setAccordion"
                script="viewScope.put('accordion', selected);">
                <xe:this.arguments>
                    <xe:remoteMethodArg name="selected" type="string" />
                </xe:this.arguments>
            </xe:remoteMethod>

        </xe:this.methods>
    </xe:jsonRpcService>
<xp:button id="btnTriggerRPC" value="Trigger RPC Method">
        <xp:eventHandler
            event="onclick"
            submit="true"
            refreshMode="complete">
            <xp:this.script><![CDATA[if ($('#collapseOne').attr('aria-expanded') == "false") {
rpcService.setAccordion('collapsed');

}else{

    rpcService.setAccordion('expanded');
}]]></xp:this.script>
        </xp:eventHandler>
</xp:button>
0
votes

If you use your browser developer tools and see whats on the browser, you'll see the root of the problem. SSJS runs on the server only and the outcome of the code is injected into the CSJS function and passed to the browser. CSJS runs on the browser only and can't run on the server.

The CSJS is just a string to be passed to the browser. Look at the local\xsp folder in Package Explorer and find your XPage. The "if" statement can't run on the server, just everything within the #{javascript:...}.

Sven's right, on page load and every refresh, you're calling viewScope.put() to set the value to "collapsed" and to "expanded". You're running both because there is no "if" statement in the SSJS.

This may help clarify https://www.intec.co.uk/understanding-ssjs/ and I'm sure I've covered this in one of my TLCC webinar videos. You need to pass something via CSJS to a Hidden Input field, then you can access the Hidden Input in your SSJS and use that to manage the state of the accordion.

You're basically needing to build in your own state management for a custom JavaScript widget, something XPages handles for its own widgets automatically, as I described here https://www.intec.co.uk/what-domino-makes-trivial-number-one-state-management/.