There are a number of different places from which you can execute client-side JavaScript upon clicking an xp:button
. In this post, I’ll document both the order of execution and which ones execute for each refreshMode option.
Client-Side Javascript Events and Callbacks
There are 5 ways that I can see to execute client-side JavaScript when a button is clicked.
The easiest way is the “Client” event tab. Use the script editor to add code.
There are also 3 callbacks on the event handler (onStart, onComplete, onError
) where you can add client-side JavaScript. These are a little harder to get to — you have to switch to the Source view, click on the xp:eventHandler
tag, and then find them in All Properties
under the events
category.
You can also run client-side JavaScript from an SSJS code using the view.postScript() method. (Here’s an example snippet from Russ Maher) This is a bit more complex because you need to get code into a string (watch the quotes closely!), but it works well.
Here’s an example:
view.postScript('alert("server event - view.postScript");');
An Example
Here’s an example of a button that makes use of all 5 options. xp:this.script
is the client-side event. xp:this.action
is the SSJS event code with the view.postScript
call. onComplete
, onError
, and onStart
are part of the xp:eventHandler
itself.
<xp:button value="Refresh Fields 2-4" id="button2"> <xp:eventHandler event="onclick" submit="true" onComplete="alert('server event callback - oncomplete');" onError="alert('server event callback - onerror');" onStart="alert('server event callback - onstart');" refreshMode="partial" refreshId="field1"> <xp:this.script> <![CDATA[alert('client event');]]> </xp:this.script> <xp:this.action> <![CDATA[#{javascript:view.postScript('alert("server event - view.postScript");');}]]> </xp:this.action> </xp:eventHandler> </xp:button>
Order of Execution
The callbacks that run very based on the refreshMode
property of the event.
If the page is fully refreshed, then none of the event handler callbacks are triggered. If the event is set to No Update or No Submission, then view.postScript
will not run.
Here is the order of execution for each event and callback (with the exception of onError
, because it would break the flow) that runs, based on the refreshMode:
- Full Refresh — client event, view.postScript
- Partial — client event, onstart, view.postscript, oncomplete
- No Update — client event, onstart, oncomplete
- No Submission — client event
The only way they all run is with a partial refresh.
Generated Code in the Browser
Here’s what gets generated and passed to the browser for our sample button (when set to partial refresh). The client-event code is defined in its own function. In the XSP.attachPartial() call, the client side event handler function and the callback functions are all passed (along with the button ID, refresh target ID, etc)
<script type="text/javascript"> function view__id1__id13_clientSide_onclick(thisEvent) { alert('client event'); } XSP.addOnLoad(function() { XSP.attachPartial("view:_id1:_id13", "view:_id1:button2", null, "onclick", view__id1__id13_clientSide_onclick, 2, "view:_id1:field11", "alert(\'server event callback - onstart\');", "alert(\'server event callback - oncomplete\')", "alert(\'server event callback - onerror\')"); }); </script>
The Client-Side Javascript Event vs the onStart Callback
Of particular interest to me is the distinction between the onStart
callback of a server side event and the client-side JavaScript event.
I like the concept of the onStart
callback, because your code can be consistent if you’re also running code onComplete
, however, the client-side JS event is easier to get to and it also has the ability to return false and cancel execution of the server-side event. (The onStart
callback throws an error if you try to return false, because it’s not a function.)
If you have any other insight into the differences or a benefit to using the onStart callback of the event handler, I’d love to hear it.
