Subscribe via Feed

Dynamically binding multiple querySave/postSave actions

Tommy Valand, Mar 18, 2010 4:52:14 PM

One of many things I miss in XPages is the possibility to dynamically bind multiple event listeners per document event (e.g. querySaveDocument). You can dynamically bind a single document event quite easy.

In beforePageLoad:

var application = facesContext.getApplication();
var methodBinding = application.createMethodBinding( '#{javascript:yourCode}', null);
// get(0) -> The first data source in the page
view.getData().get(0).setQuerySaveDocument( methodBinding );

The problem with the above code, is that if someone puts querySaveDocument code in the XPage you're setting the above event, that code is overwritten/ignored.

I've written some Server Side JavaScript that lets you queue multiple SSJS actions on querySaveDocument and on postSaveDocument. The other document-events seem to be initiated before beforePageLoad, so you can't add additional code to those dynamically.

Adding an action works like this:

  1. Check to see if the page has an embedded event handler
    1. If yes, store the method binding for the event in a viewScope-variable
  2. Add action to an ArrayList inside a scoped variable
  3. Overwrite the event handler so that it calls a method that runs the embedded event handler + the queued actions

When the event runs:

  1. If there was an embedded event handler for the event in the page, run this
    1. Test the result of the event handler.  If result === false -> don't run the queued actions, as they may interfere with the intended flow of events
  2. Execute all the actions in the queue

Example usage (beforePageLoad):

Events.addToDocumentEvent( 'querySaveDocument', 'xspTestDoc.setValue( "description", "Overridden" )' );

Add the events in the beforePageLoad on the page.

Why would you want to bind events dynamically?

In an XPages application I'm working on, I've made a custom control that's similar to a "prevent save conflicts" custom control I wrote about a in my blog a little while back. 

The difference between the one I posted, and the one in the application is that it uses a custom field on the document. The field is used to test if the document has been modified by a user. When a user saves a document, the field value is set to @Now().

The custom control I wrote about earlier uses the "@Modified-value" that's set whenever a document is modified.

The custom control in the application I'm working on dynamically adds a little querySaveDocument code so that the modified-by-user field is set when the document is saved. This code has to work alongside existing code in the querySaveDocument-event.

2 responses to Dynamically binding multiple querySave/postSave actions

Tommy Valand, May 8, 2011 5:12 PM

Fixed. Thanks for letting me know.

Dominik Myszkowski, May 8, 2011 10:48 AM

You have a syntax error in script. Parameter "dataSourceId" is written as "datasourceId" in the body of function "addToDocumentEvent".