Your Development & Design Resource
IBM Domino XPages SSJS Object Literal Primer
03/03/2016 by Chris Toohey
Our example Object has four properties, each with a different type:
To use these properties, you can use the following syntax:
The above example script will print Number "1" to the web browser console.
Fairly simple and standard... but this becomes amazingly powerful when you realize that you can create Methods as well as Properties. Let's revisit our example:
Now, to use our new Method:
Let's take this a step further:
And now if you wanted to print Number "2" to the web browser console...
Let's say we have a time tracking app that consists of (stateful) "punch" records. Each "punch" will be a notesDocument.
Standard stuff really... which is why this is a perfect example for a simple SSJS implementation of business and application logic. And our "application.jss" library will handle all CRUD (Create, Read, Update, and Delete) operations for our "punch" and "employee profile" records.
There's a lot to cover here...
First, you may be wondering why we're using method names like
foo(), but that doesn't make for readable code.
.submit() is also a reserved word, but I've yet to run into a conflict using it as a method name. YMMV, so feel free to name your method something like
.crudSubmit() if you want to protect yourself and your production code.
Second, you may notice the use of
arguments used to allow for conditional parameters to be passed through and used by a method. The
.remove() functions all allow you to pass through a notesDocument for processing.
We'll cover several use cases for how we're using the conditional notesDocument argument (
arguments) later in this article.
On line 83 of our example, you'll see a reference to a conditional second argument for the
.remove() method. Should be easy enough to understand the use case for this one.
Third, lines 11, 36, 56, and 77 reference
utilities.wrapNotesDocument(arguments);. This is actually a use of the
wrapNotesDocument() method of the
utilities Object found in the "core.jss" SSJS library.
Use Case: Conditional Validation and Error Reporting
Our time tracking example application will allow you to save a "draft" status punch notesDocument at any time, but we want to validate the punch for required fields when we change the status from "Draft" to "Submitted for Review".
Here's the pseudocode breaking down our conditional validation:
Check all required fields.
Change "status" field to "Pending Review".
Save the "punch", and then open it in read mode.
Warn the user of the missing or malformed form data.
Now let's take a look at the
The above method refers to several methods from my
utilities object. As mentioned, these libraries can be created and expanded over time creating an evolving functional toolkit for your application development needs.
... but back to the above function specifically. The
finally block will check to see if the
rBoolean is true/false. If true - meaning it passed our validation - it will call the
punch.submit() method... which itself returns a Boolean.
In other words, once we've validated the "punch", we try and save it. If it saves without an error, we open the "punch" in read mode.
Now let's look at the "Submit for Review" button that will sit at the top of our XPage "punch" form:
onclick eventHandler is using a Partial Refresh so - in the event of a validation failure - we can simply paint the UI while maintaining the scoped data.
UI Validation Message for 'datepost' Field.
If the validation passes, the
punch.open() method is eventually called which uses a
context.redirectToPage(), thus navigating the user away from the Partial Refresh'ed XPage to the read mode version of the updated "punch".
We included the
punch.open() methods in the
punch.submitForReview() method as an example. Ideally we would return a Boolean for each of those methods and use those Booleans in a more task-oriented design.
So let's revisit our
-- and now our "Submit for Review" button:
-- because if we do that, we can easily do this from a View XPage:
We've covered a lot in this primer, and we've only scratched the surface.
As mentioned, I have a library of core utility methods that have become my Go To methods when coding. For example,
utilities.isEmpty() has replaced my
undefined checking. If I want to write a validation error to the screen or a simple "Hey, you did it!" message I use my
The core library will grow. You may even - as I have - create a company-standard library that contains methods like
tracking.updateHistory() for updating create/read/write/delete histories and
standard.generateID() for creating a unique ID/key for a given record.
For enterprise application developers, it's critical to have easily managed and consistent code. While you can certainly do this without using the Object Literal syntax, this syntax allows for immediate code readability and recognition.
punch.open() is used to open a "punch".
employeeProfile.getPunches()... is used by the "employeeProfile.xsp" XPage to return a list (it's actually an object) containing all keyed "punch" records.
There are many reasons that I would recommend using this technique, but here's one you perhaps haven't considered: