Action Not Working With Rendered Property Set On Custom Control, Containing The Action Button
Solution 1:
You have to set option "Set partial execution mode" execMode="partial"
in your button. This will execute button's SSJS first and for sure.
Otherwise it will recalculate the whole page first without an URL parameter sDevice
. Because sDevice
is not set the XPage won't render the current part (e.g. desktop-panel) and won't execute button's SSJS. Later on client side, it will execute the partial refresh with URL parameter sDevice=desktop
and render the desktop-panel but that is too late for executing button's code.
I modified your example from your link. It prints the current URL parameter sDevice
in panel "pnlList" and prints "button clicked" when button's SSJS gets executed. The button writes a random value to viewScope variable and refreshes the "computedField1". This way you can see what happens on server console when you click the button, refresh page or resize browser window.
As you can test, button works with rendered condition (but won't work without execMode="partial"
). You can still do a full update instead of the partial refresh in example if you need to.
<?xml version="1.0" encoding="UTF-8"?><xp:viewxmlns:xp="http://www.ibm.com/xsp/core"><xp:eventHandlerevent="onClientLoad"submit="false"><xp:this.script><![CDATA[$(window).on('load resize', function(){
var screenWidth = $(window).width();
var sDevice = '';
switch(true){
case (screenWidth < 768):
sDevice = 'mobile';
break;
case (screenWidth < 922):
sDevice = 'tablet';
break;
case (screenWidth >= 922):
sDevice = 'desktop'
}
XSP.partialRefreshPost( '#{id:pnlList}', {params: {'sDevice': sDevice}} );
});]]></xp:this.script></xp:eventHandler><xp:panelid="pnlList"rendered="#{javascript:print('param.sDevice: ' + param.sDevice); return true}"><xp:labelvalue="I am going to be displayed if I am on a mobile device"id="label1"rendered="#{javascript:param.sDevice == 'mobile';}"><xp:eventHandlerevent="onclick"submit="true"refreshMode="complete"></xp:eventHandler></xp:label><xp:br></xp:br><xp:labelvalue="I am going to be displayed if I am on a tablet device"id="label2"rendered="#{javascript:param.sDevice == 'tablet'}"></xp:label><xp:br></xp:br><xp:labelvalue="I am going to be displayed if I am on a desktop device"id="label3"rendered="#{javascript:param.sDevice == 'desktop'}"><xp:buttonvalue="Label"id="button1"><xp:eventHandlerevent="onclick"submit="true"refreshMode="partial"execMode="partial"refreshId="computedField1"><xp:this.action><![CDATA[#{javascript:
print("button clicked");
viewScope.currentItem = Math.random();}]]></xp:this.action></xp:eventHandler></xp:button></xp:label></xp:panel><br /><xp:textescape="true"id="computedField1"value="#{viewScope.currentItem}"></xp:text></xp:view>
Update
Not executing buttons SSJS code is a symptom of the approach itself. The panel "pnlList" gets rendered by default empty. Only after client's load or resize event panel will be partially refreshed and be filled with a device depended content. Unfortunately, the criteria for rendering is fragile as it is only part of partial refresh URL. The button might be work with option execMode="partial"
but you might run into other issues with this approach.
The better approach is to let the client tell the server what kind of device it is and the server will save this information in an viewScope variable and the rendered conditions using the viewScope variable only. This way the server already renders the panel for the current device and will just change it on load and resize event.
Save the parameter sDevice to a scope variable panel's "pnlList" rendered property (return always true) and use this variable in rendered condition in device specific panels:
<xp:panel
id="pnlList"
rendered="#{javascript:if (param.sDevice) {
viewScope.device = param.sDevice;
}
return true}">
<xp:button
value="Button Mobile"
id="button1"
rendered="#{javascript:viewScope.device == 'mobile';}">
...
Post a Comment for "Action Not Working With Rendered Property Set On Custom Control, Containing The Action Button"