Monday, September 14, 2009

XPages Custom Control - getComponent/hash of all clientIds from the browser

Until IBM implements getComponent in the browser, I've made a litte experimental custom component that lets you do something similar to getComponent in server side scripting. So far it only works with unique components (doesn't work with repeated items).

The component adds a script-tag at the bottom of the page, using the output stream that you get from facesContext.

The API is small:
Application.renderedIds
An object containing { designerId: clientId(s) } for all (?) components in the XPage. If there are multiple versions with the same designer id, you'll get the wrong id. (see comments)

Application.getComponent( designerId )
Similar to the getComponent in Server side JS. Fetches the rendered id from Application.renderedIds, then uses the corresponding clientId in a document.getElementById-statement. This method will fail if you try to multiple controls that has the same designerId (repeated items for instance).



Comments/bugreports/wishes are appreciated (but I can't promise anything).

I'm probably going to start working on a big XPage application along with some colleagues in the near future, so it's not impossible that I might turn this into a client side utility component. Time will tell.

>> Demoapp with Custom Control (GetComponentClient)

4 comments:

jeremy.hodge said...

Without having downloaded the code, I'm wondering how you are handling items within a repeat control where there are multiple instances if component 'X'?

Tommy Valand said...

As mentioned in the post, the code is run at "afterRenderResponse". I believe this means that all components are calculated and ready to be sendt to the browser.

The keys in the hash are the components names (in the designer). If a component with an id is already in the hash, I change the clientId to an array (of clientIds). For every component with similar id, the clientId is appended to the array.

This is 2-3 hours of work, so I don't pretend for this to be a complete solution yet. It doesn't cover partial updates for instance, but I believe this should be possible to achieve as well.

Don't take this from the horse's mouth. Download, and try for yourself. All you have to do is to include the custom component on an XPage. Test the mini API with Firebug or similar tools.

Tommy Valand said...

I spoke too soon. getClientId returns something like this for a repeated item:
view:_id1:_id10:repeatList:linkExpand

Whereas the rendered repeated items has an index:
view:_id1:_id10:repeatList:[index]:linkExpand

E.g.
view:_id1:_id10:repeatList:5:linkExpand

I can't say when, but I will dig deeper into the clientId-issue. Until then, you can use this on all items with unique ids.

quintiexxx said...

getComponent("button1").getClientId(facesContext)