I’ve recently been looking back at an application I added some XPages functionality into a while ago and realised there were a couple of Server-Side JavaScript tips I have not shared before.

The first is actually unnecessary where I’ve used it. I think Tim Tripcony mentioned it and I started using it all over the place at the time and subsequently forgot about it completely. With scoped variables in particular, when they are bound to a control on the XPage, the scoped variable has a value once the page is partially refreshed. But when the page is first loaded, the scoped variable is null unless you set it in the beforePageLoad. That means if you use if (viewScope.myVal=="") it throws an error. So you end up putting if (viewScope.myVal==null || viewScope.myVal==""), while thinking, “There must be an easier way”.

Well, there is. if (!!viewScope.myVal). No, it’s not a typo. The double exclamation mark is a JavaScript construct that does all sorts of checking that a value is not truthy. A good explanation (thanks Thimo Jansen for finding the link) is on Stack Overflow. Assuming myVal should be a string, if it is null or empty, it returns false; if it has a value, it returns true. The point to bear in mind is that it returns true for an empty array or object. And in my particular scenario I was using it for the output of getItemValueString(), which is null safe. So if the item is null, the value returned is “” nonetheless. The only benefit of !! in this scenario is it’s two less characters than ==””.

The second tip is on error handling in SSJS. Whether you’re using OpenLog, Mark Leusink’s Debug Toolbar or something else, you should always, always, always have error handling in your SSJS. “Error while executing JavaScript expression” on an XPage is great if you want to waste an afternoon trying to find an error because you didn’t consider a particular scenario. Error handling will ensure you can do something more productive instead.

But the inbuilt SSJS error handling will tell you which page the error occurred on, on the whole, but little more. In this particular application I was consistently using:

try {
...
} catch(e) {
dBar.error(e.toString() + ": " + this.getParent().getId();
}

On my event handlers this logged the component’s ID – this.getParent() retrieves the parent of the event handler, namely the component. Of course, you need to think about default IDs because if you drop a button on an XPage, the ID will be button1. If you drop a button on a custom control within that XPage, it will also be button1. But it does allow easier tracking of where the error occurred. Also, bear in mind this will be useless in SSJS Script Libraries, because there’s no way to access the component. But you could pass the component ID to script libraries for error handling.

2 thoughts on “A Couple of SSJS Usability Suggestions”

  1. I’d suggest using this.getParent().getClientId(facesContext) instead… not only does that provide more contextual information, if the event was triggered from inside a repeat, you’ll even know which row the event occurred in.

    You could also report the component class using one of two syntaxes:

    typeof this.getParent()

    this.getParent().getClass().getName()

    So if your ID is still button1 even though you later changed it to a link, this can help to avoid hunting for a component that doesn’t exist.

    1. When I was reviewing what I’d done I did think about client ID, but in this scenario amongst other controls I’m using the dynamic form method, so row could vary depending on a variety of contexts. Considering it’s XPiNC, identifying the client ID could actually be more difficult than finding out which row, for errors within a repeat. But it’s certainly an option and once you have the component there’s a wealth of options you can use. I guess you could even add an attribute for a row’s doc ID to the parent control and retrieve that.

Leave a Comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.