Saturday, February 27, 2010

XPages: Use converters to emulate domino computed fields

I don't have much time to write this (people to meet, stuff to do), so I'll keep it short.

One of the things I really missed going from standard Domino development to XPages development is the (Domino) computed fields.

When I woke up this morning, I thought "what about converters?". Tested it out, and it works! :)

In the getAsObject-code (all properties), you write the code that computes the field.
var numItems = getComponent( 'numItems' ).value;
var price = getComponent( 'price' ).value;
return (numItems && price) ? numItems * price : 0;
The above example stores the value as number, so in getAsString, you have to convert the number to string (value is a local variable containing the value of the field):
value.toString();
I didn't have much time to test, so I don't know all the weaknesses with this technique. One thing I found. If the field is set to read only, the converter is ignored/the value is static.

The technique should work great for hidden fields that have dynamic values. It lets you have all the computing code relevant to the field in the field (instead of setting the field form other fields' events, or in XPages events).

If you can think of other ways to use this technique, please leave a comment.

Monday, February 22, 2010

XPages: Using an array of objects in property definitions

If you want to use a complex JavaScript object in property definition for a custom control, write object in Type.

Example:

Wednesday, February 17, 2010

XPages API Inspector V2

The changes from the previous version are quite big (as you can see from the screenshots below).

From what I can remember:
* Methods are now sorted alfabetically

* If the returned class/the class of the (inherited or local) method is
from the JSF 1.0 or Java 6 API, I've added a direct link
into Sun's APIs. Google search link always added.

* Declared Methods, Methods, Declared Fields and Fields are organized in
their own section.

* Each section has the number of contained items next to the title

* Private methods/fields have been removed from the report

(Google idea robbed and deployed from Nathan T. Freeman google)

Overview:


Methods:


The best thing? I only needed an evening to make the changes. That's RAD!

>> Download from OpenNTF
No login is required for download. If you don't like version 2 (let me know why), version 1 is also available.

As with the previous version, all code is contained in the custom control. This is sometimes a headache to work with (for me), but it makes it extremely easy to implement the control.

Let me know if there are any bugs.

Share and enjoy!

Update: dijit.Dialog custom control fixup

Just wanted to let you know that I've updated and improved the demoapp from yesterdays post.

The custom control is self-contained, but I recommend moving the client side script at the bottom of the source code into a javascript library.

I've implemented Mark Hughes code (thanks for the tip, Julian), which is a lot more general than my hacks.

>> Download demoapp

Let me know if you find any bugs..

XPages: Use MooTools in Server Side JS

I wanted to filter/extract values from an array of objects today. Before I started reinventing the wheel, I took a look at MooTools' server side library. It contains a lot of syntactical sugar.

The code needed to extract email addresses from an array of JS-objects, using MooTools (data is an array of objects):
var emailAddresses = data.map(function(item){
return item.email || null;
}).clean();

Download here.
General MooTools documentation here.

Tuesday, February 16, 2010

XPages: Making dojo dialogs works with server-side events

Julian gave me a link to a cleaner way of making dialogs work. I recommend using that method instead of what's below.

As I've mentioned several times, I'm currently working on a larger project that relies heavily on XPages technology.

One of the widgets I felt the need for in this project is the modal dialog box. Dojo has two inbuilt widgets that provides this functionality, dijit.Dialog, and dojox.widget.Dialog.

As Julian Buss points out, you'll stumble onto a couple of big problems when using these widgets in XPages (out of the box). Server side events aren't triggered, and field values aren't posted to the server. I've used more time than I want to admit, trying to find out why server side events doesn't work. The answer is quite simple.

XSP.getForm

Actions that triggers server side code (partial-/full refresh) need to know which <form> to post. When an event is triggered, the DOM tree is traversed upwards until a form is found/the top of the tree is reached. If a form isn't found, the event is ignored. The dialog widgets in Dojo are moved to the bottom of <body>, outside any form tags.

Client side JS to "fix" XSP.findForm:
/*
Modifies XSP.findForm so server side events are fired correctly when
dojox/dijit dialogs are used.
- First try the native findForm-method to find the correct form
- Then try to find a parent element with the attribute form_id (used specifically in ccModalDialogWeb in this demoapp)
- If everything else fails, return the first form on the page.
*/
dojo.addOnLoad(function( el ){
var oldFn = XSP.findForm;
XSP.findForm = function( el ){
var form = oldFn.apply( this, arguments );

if( !form ){ // Look for element with form_id attribute
el = (typeof el === 'string' ) ? dojo.byId( el ) : el;
if( el && el.nodeName ){
while( el && el.nodeName !== 'BODY' ){
var formId = el.getAttribute( 'form_id' );
if( formId ){ // form_id found -> get form by id
form = dojo.byId( formId );
break;
}

el = el.parentNode;
}
}
}

return form || document.forms[0];
}
});

Only server side events from the the dojo dialog (/any other elements triggering server side events outside forms) are affected by this code. First the original XSP.getForm is tested (so that "standard" events arent't broken). If no form is found, the DOM tree is traversed upwards looking for an attribute, form_id, which can be added to one of the parent elements of the dialog content. If form_id is found, it's used to locate the correct form. If that also fails, the first form on the page is used. I use form_id in the demoapp. This is not a native attribute, so you have to generate this yourself. getForm.getClientId(facesContext) returns the browser-id of the parent form.

The above code doesn't fix the problem with fields being moved outside the form. In the demoapp, I've made a simple workaround for this (only for input-fields). Basically you have to clone the fields in the dialog, and copy them onto the correct form. Add an onChange event to the dialog fields, so that the clones get the correct value.

If you decide to implement the custom control in your own projects, and need workaround for other field types, let me know.

The demoapp contains a custom control that let's you open another custom control/xpage inside another XPage. If you use a custom control for the dialog, the custom control should have full access to the XPage that contains the dialog.

The interactive part of the demoapp is extremely simple. The "gold" is the custom control ccModalDialog, and the client side script, ccModalDialog.js.

Hopefully IBM implements a standard control for modal dialogs. It's not impossible to make perfect. It only requires time, knowledge and patience.

>> Download demoapp

Share and enjoy!

Wednesday, February 10, 2010

IBM Support Assistant

Just discovered the IBM Support Assistant search. It seems to be a mashup of different search engines.

Available in Domino Designer from
Help -> Support -> IBM Support Assistant


Monday, February 1, 2010

Another small update on the XPages API Inspector

I've added a clear-button, and a subheader with the toString-value that's visible if the expression corresponds with a server side object.

@Now()


>> Download tool

>> Original post with description