Tuesday, November 10, 2009

XPages: Creating a Data Table programmatically on page load

I've finally started working on a proper XPages application at work, so now my inspiration is bubbling.

Todays demo is (hopefully) a precursor to something that will be very useful to you, my readers. I started looking for a way to dynamically creating a Data Table control. Since XPages still is in its infancy, documentation and examples-wise, I had to go look for information on JSF (which XPages is built upon).

I found this great resource. The classes used for UIComponents in XPages have different names than the standard JSF-classes, but the syntax is more or less the same.

To find the XPages equivalent classes, I create the component I want to find the class for. Set an id to it. Then I create a computed field with the value of typeof getComponent( 'componentId' ). This returns the full class name of the component. E.g. the class for DataTable is com.ibm.xsp.component.xp.XspDataTableEx.

In the demo I've made, I create a Data Table control inside an empty Panel component. The panel's data binding is a sessionScope variable. The XPage has a couple of buttons that lets you change the data of the table. The buttons do a partial update on the dynamically created table.

Screenshots of demoapp:






>> Download demoapp

This "technique" can easily be used for programmatically modifying existing Data Tables at runtime as well. Take a look at the code, and get inspired.. :)

Share and enjoy!

6 comments:

klehmann said...

Thanks for sharing, great example!
I'm currently working on something similar for a project, but with a tree structure instead of a flat table. The tree structure renders the complete UI of a web application based on a Java object tree (UI model).
I'm going to write a link to your article in a new posting for my XPages series about leveraging JSF features. You can find it here. Press the XPages category to see the complete list of articles.

Tommy Valand said...

I'm already a subscriber to your blog. You have some great information there. :)

Hopefully your customer will let you share some of your tree structure techniques. Since IBM is so lazy with documentation (beyond the basic), I feel it's up to everyone in the Notes/Domino community to share their wealth of knowledge.

Andrew said...

Hi!

Thanks for the advice! It exactly what I need now to create complicated dataTables (with dynamic categorization, sorting and so on).

But I faced with issue, which can’t solve already for several hours: it’s creation of the pager control for the created table.

The code is like the following:

XspDataTableEx table = new com.ibm.xsp.component.xp.XspDataTableEx();
table.setId(“testTable”);
**** table creation related stuff ****
parentDiv.getChildren().add(table); // table successfully created

XspPager pager = new XspPager();
pager.setFor(table.getId());
pager.setPartialRefresh(true);
pager.setLayout("Previous Group Next");
pager.setId("pager1");
parentDiv.getChildren().add(pager); // pager is not created

Would you share any ideas, what is wrong?
Thanks in advance!

--
Regards,
Andrew

Tommy Valand said...

The pager is a facet of the DataTable.
Here's some pseudocode that might work (check the XPages/JSF API for proper terms).

Map tableFacets = table.getFacets();
tableFacets.put( "header", pager );

Base API for all UIComponents:
http://docs.oracle.com/cd/E17802_01/j2ee/j2ee/javaserverfaces/1.1_01/docs/api/javax/faces/component/UIComponent.html

Andrew said...

Tommy, thanks for your quick feedback!
…but not working… (
Area in header is created, but it’s absolutely blank…

I did try add pager as facets as well as separate component, but still no progress. (
I think, I lost some obvious method which will make pager work.
I will keep trying and let you know when I find the reason!

--
Best regards,
Andrew

Andrew said...

woo-hoo!! Solved! Found the reason!! ))
The magic phrase to be added is: pager.initAfterContents(facesContext);

So, based on given source code example, it should look like:

XspDataTableEx table = new com.ibm.xsp.component.xp.XspDataTableEx();
table.setId(“testTable”);
**** table creation related stuff ****
parentDiv.getChildren().add(table);

XspPager pager = new XspPager();
pager.setFor(table.getId());
pager.setPartialRefresh(true);
pager.setLayout("Previous Group Next");
pager.setId("pager");
pager.initAfterContents(FacesContext.getCurrentInstance());

and last either:
parentDiv.getChildren().add(pager);
or:
table.setFooter(pager);

BTW: pager will work as separate component, as well as facet of the dataTable.