|
Page 1 of 6
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"
<< Start < Previous 1 2 3 4 5 6 Next > End >> |