XPages Developer
Interests: Developing web and mobile apps
Skills: JavaScript, HTML, CSS, Java, Dojo, jQuery, IBM Lotus Notes and Domino, iWidgets, OpenSocial, Activity Streams
Location: Everywhere
Hobbies: Writing great code that helps people and businesses get stuff done. Love pizza, good music, good friends and beach combing.
Subscribe via FeedPaul Withers, Apr 29, 2010 7:55:45 PM
I picked up a few queries about how to use the output from server-side javascript in client-side javascript. I've learned with XPages that there are usually many ways to produce the same result. Here's the method I came up with. I don't know if it would be considered best practice, and I'd be interested to hear alternatives other developers have used.
One caveat is that this method uses the onComplete event of a partial refresh, which is only available from 8.5.1. You can see it in action here. The XPage has a button that alerts the user with the database created date and replica ID.
Initially you might expect that the button calls the client-side javascript alert function. But if you refresh the page and look at the source HTML, you'll see it's not running client-side javascript. You'll also see that nowhere in the source HTML is the database created date and replica ID. What you will see is a partial refresh and, within that, a client-side javascript alert function referring to a hidden input and a span. Both are initially empty. A look at the code will explain what's happening.
viewScope.SSJS_Return = database.getReplicaID()}]]>
The button uses server-side javascript to set a value in the xp:inputHidden and set the viewScope variable. It then does a partial refresh of refreshPanel. That means the source HTML for that panel is refreshed and the values become available for client-side javascript. Put the xpInputHidden and xp:text outside the panel you're refreshing and it won't work.
The key though is in the onComplete. You need to look at the All Properties panel to find it, along with the onStart and onError events. These are all client-side javascript functions. You can use server-side javascript to compute a value for the events, but the outcome of the computation must be able to be evaluated as client-side javascript (e.g. "alert('Hello world')"). The onStart will run before the partial refresh, the onError will run if it fails, the onComplete if it is successful. So the onComplete means we can run client-side javascript code using the output of the server-side javascript. We use dojo.byId() to get the field and the span, and alert the user with the values.
It's a simple technique, but one which could have extended applications for alerting the user as we're doing here. Made simpler, we could just populate the viewScope variable, and set dojo.byId().style.visibility="visible" to display the message in its xp:text. Or, extending it further, we could populate content in and showing a dijit.Dialog.
3 responses to Calling Client-Side Javascript from Server-Side Javascript
Hanspeter, January 18, 2011 5:35 PM
Thanks for that tip Jens. I searched since hours for a solution..
Jens Winkelmann, July 14, 2010 2:26 PM
Sorry, one row was not complete:
replace
var flag = "#{
by
var flag = "#{java script:requestScope.pleaseAlert}";
Jens Winkelmann, July 14, 2010 2:17 PM
Excellent solution.
I asked myself what do you have to do when the button should do a full update.
The onComplete event is not available when you do a full update.
Here my solution:
<xp:button value="Trigger Full Update" id="button2">
<xp:eventHandler event="onclick" submit="true"
refreshMode="complete">
<xp:this.action><![CDATA[#{
viewScope.SSJS_Return = database.getReplicaID();
requestScope.pleaseAlert = "1";
}]]></xp:this.action>
<xp:this.onComplete><![CDATA[alert("Database was created on " + dojo.byId("#{id:inputSSJS}").value + ". Database replica ID is " + dojo.byId("#{id:textSSJS}").innerHTML)]]></xp:this.onComplete>
</xp:eventHandler></xp:button>
<xp:scriptBlock id="scriptBlock1">
<xp:this.value><![CDATA[
var pleaseAlert = function() {
var flag = "#{
if( flag == "1" ) {
alert("Database was created on " + dojo.byId("#{id:inputSSJS}").value + ". Database replica ID is " + dojo.byId("#{id:textSSJS}").innerHTML);
}
};
XSP.addOnLoad(pleaseAlert);
]]></xp:this.value>
</xp:scriptBlock>
The server-side code sets a requestScope variable 'pleaseAlert' with the value '1'.
The client-side code is written in a scriptBlock.
Via the addOnLoad event the requestScope variable is inspected and the alert will be triggered if the requestScope has been set.