Java J2EE Portal
Enterprise Java Station
J2EE curve
Java News / Articles
Java News / Articles
India Java User Groups
Continuous Integration - Agile Software Development Q & A
Building User Interfaces Using Google Web Toolkit (GWT)
Processing...
Buy Java, Deals On Software Technology Store
Click here for great deals on computers, laptops, software and books
Building Advanced Components For Tapestry Web Applications PDF Print
Written by Alexander Kolesnikov   
Feb 14, 2008 at 02:50 AM
Tapestry 5 In this excerpt from the book Tapestry 5: Building Web Applications author Alexander Kolesnikov looks at building advanced components. Tapestry is an Apache open-source framework for creating dynamic, robust, highly scalable web applications in Java. The book is a step-by-step guide to Java Web development with the developer-friendly Apache Tapestry framework.

Advanced Components

We are already familiar with a significant number of Tapestry components, and using them, we can build sophisticated and functionally rich interfaces. It so happens however, that many web applications have certain patterns repeating on their pages. For example, they have tables that display different data or they have forms that accept user input and then put the submitted details into some kind of Java Bean object. Wouldn't it be convenient to have such repeating patterns already implemented as components, ready to be dropped onto a page? It certainly would, and the current version of Tapestry 5 already comes with a few components of this kind. They are great effort savers for us, and in this chapter we are going to introduce them and use them in our Celebrity Collector application.

Following are some of the components, we'll examine:

  • The Grid component allows us to display different data in a fairly sophisticated table. We are going to use it to display our collection of celebrities.
  • The Bean EditForm component greatly simpli fies creating forms for accepting user input. We shall use it for adding a new celebrity to our collection.
  • The DateField component provides an easy and attractive way to enter or edit the date.
  • The FCKEditor component is a rich text editor, and it is as easy to incorporate into a Tapestry 5 web application, just as a basic TextField is. This is a third party component, and the main point here is to show that using a library of custom components in a Tapestry 5 application requires no extra effort. It is likely that a similar core component will appear in a future version of the framework.

Grid Component

Previously, we were able to display our collection of celebrities with the help of the Loop component. It wasn't dif ficult, and in many cases, that will be exactly the solution you need for the task at hand. But, as the number of displayed items grow (our collection grows) different problems may arise. We might not want to display the whole collection on one page, so we'll need some kind of a pagination mechanism and some controls to enable navigation from page to page. Also, it would be convenient to be able to sort celebrities by first name, last name, occupation, and so on. All this can be achieved by adding more controls and more code to finally achieve the result that we want, but a table with pagination and sorted columns is a very common part of a user interface, and recreating it each time wouldn't be ef ficient. Thankfully, the Grid component brings with it plenty of ready to use functionality, and it is very easy to deal with. Open the ShowAll.tml template in an IDE of your choice and remove the Loop component and all its content, together with the surrounding table:

<table width="100%">
  <tr t:type="loop" t:source="allCelebrities"
     t:value="celebrity">
  <td>
    <a href="#" t:type="PageLink" t:page="Details"
    t:context="celebrity.id">
    ${celebrity.lastName}
    </a>
  </td>
  <td>${celebrity.firstName}</td>
  <td>
      <t:output t:format="dateFormat"
      t:value="celebrity.dateOfBirth"/>
  </td>
      <td>${celebrity.occupation}</td>
  </tr>
</table>

In place of this code, add this line: <t:grid t:source="allCelebrities"/>

Run the application, log in to be able to view the collection, and you should see the following result:

Quite an impressive result for a single short line of code, isn't it? Not only are our celebrities now displayed in a neatly formatted table, but also, we can sort the collection by clicking on the columns' headers. Also note that occupation now has only the first character capitalized—much better than the fully capitalized version we had before.
Here, we see the results of some clever guesses on Tapestry's side. The only required parameter of the Grid component is source, the same as the required parameter of
the Loop component. Through this parameter, Grid receives a number of objects of the same class. It takes the first object of this collection and finds out its properties. It tries to create a column for each property, transforming the property's name for the column's header (for example, lastName property name gives Last Name column header) and makes some additional sensible adjustments like changing the case of the occupation property values in our example.

All this is quite impressive, but the table, as it is displayed now, has a number of deficiencies:

  • All celebrities are displayed on one page, while we wanted to see how pagination works. This is because the default number of records per page for Grid component is 25—more than we have in our collection at the moment.
  • The last name of the celebrities does not provide a link to the Details page anymore.
  • It doesn't make sense to show the Id column.
  • The order of the columns is wrong. It would be more sensible to have the Last Name in the first column, then First Name, and finally the Date of Birth.

By default, to de fine the display of the order of columns in the table, Tapestry will use the order in which getter methods are de fined in the displayed class. In the Celebrity class, the getFirstName method is the first of the getters and so the First Name column will go first, and so on. There are also some other issues we might want to take care of, but let's first deal with these four.

Tweaking the Grid

First of all let's change the number of records per page. Just add the following parameter to the component's declaration:<t:grid t:source="allCelebrities" rowsPerPage="5"/> Run the application, and here is what you should see:
You can now easily page through the records using the attractive pager control that appeared at the bottom of the table. If you would rather have the pager at the top, add another parameter to the Grid declaration:

<t:grid t:source="allCelebrities" rowsPerPage="5"pagerPosition="top"/>

You can even have two pagers, at the top and at the bottom, by specifying pagerPosition="both", or no pagers at all (pagerPosition="none"). In the latter case however, you will have to provide some custom way of paging through records.

The next enhancement will be a link surrounding the celebrity's last name and linking to the Details page. We'll be adding an ActionLink and will need to know which Celebrity to link to, so we have the Grid store using the row parameter. This is how the Grid declaration will look

<t:grid t:source="allCelebrities" rowsPerPage="5"
    row="celebrity"/>

As for the page class, we already have the celebrity property in it. It should have been left from our experiments with the Loop component. It will also be used in exactly the same way as with Loop, while iterating through the objects provided by its source parameter, Grid will assign the object that is used to display the current row to the celebrity property.

The next thing to do is to tell Tapestry that when it comes to the contents of the Last Name column, we do not want Grid to display it in a default way. Instead, we shall provide our own way of displaying the cells of the table that contain the last name. Here is how we do this:

<t:grid t:source="allCelebrities" rowsPerPage="5"
   row="celebrity">
   <t:parameter name="lastNameCell">
     <t:pagelink t:page="details"        t:context="celebrity.id">
         ${celebrity.lastName}
       </t:pagelink>
     </t:parameter>
</t:grid>

Here, the Grid component contains a special Tapestry element <t:parameter>, similar to the one that we used in the previous chapter, inside the If component. As before, it serves to provide an alternative content to display, in this case, the content which will fill in the cells of the Last Name column. How does Tapestry know this? By the name of the element, lastNameCell. The first part of this name, lastName, is the name of one of the properties of the displayed objects. The last part, Cell, tells Tapestry that it is about the content of the table cells displaying the speci fied property.

Page 1 Of 6 - Advanced Components from the book "Tapestry 5 - Building Web Applications"



Add This Feed Button

Enter your Email


Java Expert Interviews
DaveCraneAJAXinterview
Ajax technologies aren't particularly new or sexy
TitusBrown
Test Driven Development doesn't fit my brain
RichUngerNetBeans
NetBeans was the early bird but has Eclipse caught the worm?
Processing...
Go to top of page  Home |
SiteMap

Copyright 2004 to 2008 Rightrix Solutions. All rights reserved. All product names are trademarks of their respective companies. Java and all Java-based marks are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries. Rightrix Solutions and IndicThreads.com are independent of Sun Microsystems, Inc.

Views expressed at IndicThreads.com reflect the views of the authors alone, and do not necessarily reflect those of IndicThreads.com. IndicThreads.com and it's authors are not responsible for reader comments and opinions.

Enterprise Java J2EE JEE Portal >> IndicThreads.com