Basic

Basic
Help ! I am new to the collection tag !

Very simple example. Let's suppose there is a collection under the name "users" in the request scope which contains object having the properties login, firstname, lastname, and society

...
<layout:collection name="users" styleClass="ARRAY"> 
	<layout:collectionItem title="users.login" property="login"/> 
	<layout:collectionItem title="users.firstname" property="firstname"/> 
	<layout:collectionItem title="users.lastname" property="lastname"/>
	<layout:collectionItem title="users.society" property="society"/> 
</layout:collection> ... 
How can I put free HTML / complex data into a column ?

Now, we want to display something very specific for the society column (for example, the society logo). We suppose the getSociety() method of the bean returns a society object which has a getLogo() method.

...
<layout:collection name="users" styleClass="ARRAY" id="user">
	<layout:collectionItem title="users.login" property="login"/> 
	<layout:collectionItem title="users.firstname" property="firstname"/> 
	<layout:collectionItem title="users.lastname" property="lastname"/> 
	<layout:collectionItem title="users.society">
		<img src="/myApplication/pathToSocietyLogo/<bean:write name="user" property="society.logo"/>" border="0"> 
	</layout:collectionItem>
</layout:collection> ... 
Where can I see the result of the example in this page ?

Click here to see the running examples

What are the basic parameters of the collection tag ?

The struts-layout collectionItem tag can be used with different parameters specified, and with or without a body content.

  • If there is a body content, the attribute named property is ignored and the body content is displayed instead of the value of the property.
  • If the attribute url is present, the property value is displayed inside a <a> tag which href attribute is the value of the url attribute.
  • If the attribute param is present too, the value of the property named param of the bean is appended to the url attribute value.
  • If if the attributes paramId and paramProperty are present instead of param, the values of the coma separated list of param properties are appended to the url with the corresponding list of param ids
  • If the attribute onclick is present, a corresponding onclick attribute is generated for the <a> tag:
<%@page import="fr.improve.struts.webapp.layout.example.User,java.util.Vector" %>
<%@taglib uri="/WEB-INF/struts-layout.tld" prefix="layout" %>
<% Vector v = new Vector();
   User user = new User();
   user.setFullName("John Smith");
   user.setUsername("jsmith");
   User user2 = new User();
   user2.setFullName("Jean Durand");
   user2.setUsername("jdurand");
   v.add(user); v.add(user2); pageContext.setAttribute("users", v);
%>
<html>
<head>
<link rel="stylesheet" href='../config/skin2.css' type="text/css">
</head>
<body>
<layout:collection name="users" title="Users" styleClass="FORM">
<layout:collectionItem title="Login" property="username"/>
<layout:collectionItem title="Name" property="fullName"/>
<layout:collectionItem title="Edit" url="collectionItem2.jsp?user=" param="username" property="fullName"/>
<layout:collectionItem title="Delete" url="collectionItem3.jsp?user=" param="username" property="fullName" onclick="return confirm('Really delete the user ?');">
<layout:collectionItem title="DoSomething" url="collectionItem4.jsp" paramId="fuLlNaMe,uSeRnAmE" paramProperty="fullName,username" property="fullName"/>
Delete
</layout:collectionItem>
</layout:collection>
</body>
</html>

Result

Nesting logic tags inside a collection tag

Nesting logic tags inside a collection tag is difficult, because the current implementation does an initial iteration to display the headers. In this iteration, no iteration bean is defined, so <logic:present> tags must be used before testing the bean value.

Selecting lines

Selecting lines
How can I select a line in the list ?

If the collection tag is nested in a form tag, it is possible to display radio buttons to select a bean in a collection.

The selectProperty attribute specifies which property of the beans should be use to set the value of the input fields generated.

The name of the input fields is the one of the selectProperty specified. It can be changed by setting the selectName attribute. In this case, the radio buttons / checkbox are checked in function of the correspondig form bean property value.

The selectType attribute can take the values "radio" or "checkbox" to allow to select one or many values.

Here is an example

In the following example, we want to be able to select one user. When we submit the form, the id parameter contains the login of the selected user.

...
<layout:collection name="users" styleClass="ARRAY" selectName="id" selectProperty="login" selectType="radio">
	<layout:collectionItem title="users.login" property="login"/>
	<layout:collectionItem title="users.firstname" property="firstname"/> 
	<layout:collectionItem title="users.lastname" property="lastname"/>
	<layout:collectionItem title="users.society" property="society"/> 
</layout:collection>
...
How can I select multiple lines in the list ?

Now, we want to be able to select multiple users. When we submit the form, the ids parameter contains the logins of the selected user. The ids property should be an indexed property in the struts bean form.

...
<layout:collection name="users" styleClass="ARRAY" selectName="ids" selectProperty="login" selectType="checkbox">
	<layout:collectionItem title="users.login" property="login"/>
	<layout:collectionItem title="users.firstname" property="firstname"/> 
	<layout:collectionItem title="users.lastname" property="lastname"/>
	<layout:collectionItem title="users.society" property="society"/> 
</layout:collection>
... 

Style and colors

Style and colors
How can I alternate the row color ?

The collection tag allows to easily alternates the row colors by using the styleClass and styleClass2 attributes.

Example:

<%@page import="fr.improve.struts.webapp.layout.example.User,java.util.Vector" %>
<%@taglib uri="/WEB-INF/struts-layout.tld" prefix="layout" %>
   Vector v = new Vector();
   User user = new User();
   user.setFullName("John Smith");
   user.setUsername("jsmith");
   User user2 = new User();
   user2.setFullName("Jean Durand");
   user2.setUsername("jdurand");
   User user3 = new User();
   user3.setFullName("Jacques Dupond");
   user3.setUsername("jdupond");
   v.add(user); v.add(user2); v.add(user3); v.add(user); v.add(user2); v.add(user3); pageContext.setAttribute("users", v);
%>
<html>
<head>
<link rel="stylesheet" href='../config/skin2.css' type="text/css">
</head>
<body>
<layout:collection name="users" title="Users" styleClass="FORM" styleClass2="FORM2" width="400">
<layout:collectionItem title="Login" property="username"/>
<layout:collectionItem title="Name" property="fullName"/>
<layout:collectionItem title="Edit" url="collectionItem2.jsp?user=" param="username" property="fullName"/>
<layout:collectionItem title="Delete" url="collectionItem3.jsp?user=" param="username" onclick="return confirm('Really delete the user ?');">Delete</layout:collectionItem>
</layout:collection>
</body>
</html>

Result

How can I highlight specific rows in the list ?

Now we want to highlight users whose firstname is Pierre. This can be done with the collectionStyle tag.

...
<layout:collection name="users" styleClass="ARRAY" id="user"> 
	<layout:collectionStyle name="user" property="firstname" value="Pierre" matchStyleClass="ARRAY2"> 
	<layout:collectionItem title="users.login" property="login"/>
	<layout:collectionItem title="users.firstname" property="firstname"/> 
	<layout:collectionItem title="users.lastname" property="lastname"/> 
	<layout:collectionItem title="users.society" property="society"/> 
	</layout:collectionStyle> 
</layout:collection> 
... 

Links

Links
I want to go to a specific page when I click on a item

Now, we want to display a link to the user information action. The action needs the login of the user to be in the parameter uid

...
<layout:collection name="users" styleClass="ARRAY">
	<layout:collectionItem title="users.login" property="login" href="user.do" paramId="uid" paramProperty="login"/> 
	<layout:collectionItem title="users.firstname" property="firstname"/> 
	<layout:collectionItem title="users.lastname" property="lastname"/> 
	<layout:collectionItem title="users.society" property="society"/> 
</layout:collection>
...

Sort

Sort
How can I allow ther user to sort the list ?

Is is possible to automatically sort a collection, on the server or on the client.

The properties of the beans that are sortable must be indicated by setting the attribute "sortable" of the collectionItem tag to true.

The sort can be done:

  • On the server with the default sorting action. The struts-layout sort action must be configured in struts-config.xml. (path="/sort", type="fr.improve.struts.taglib.layout.sort.SortAction")
  • On the server with a specific sorting action. The attribute "sortAction" and "sortProperty" of the colleciton tag must indicate the name of the struts action.
  • On the client with javascript. The attribute "sortAction" of the collection tag must be set to "client" and the file javascript.js must be included in the page (automatically done by the skin and the html tag)

There is an example of the default sort action in the demonstration, on the registration page. Here is an exemple of the javascript sort action.

By default, the sort action won't work if the back button is hit. In this case, struts-layout will detect an error and forward to an action forward named "sortError". This can be configured in the struts-layout properties file.

In the following example, we want to be able to sort the collection by users login and firstname

...
<layout:collection name="users" styleClass="ARRAY" sortAction="client"> 
	<layout:collectionItem title="users.login" property="login" sortable="true"/>
	<layout:collectionItem title="users.firstname" property="firstname" sortable="true"/> 
	<layout:collectionItem title="users.lastname" property="lastname"/> 
	<layout:collectionItem title="users.society" property="society"/> 
</layout:collection>
...

Editing data in a list

Editing data in a list
How can I make a column editable ?

If the collection tag is nested in a form tag, it is possible to put input field in the cells by using the collectionInput tag.

In the following example, we want to edit the user firstname and lastname. We can do this with the collectionInput tag. This example suppose there are two indexed properties called firstname and lastname in the form bean associated to the updateUsernames action.

...
<layout:form action="/updateUsernames"> 
	...
	<layout:collection name="users" styleClass="ARRAY"> 
		<layout:collectionItem title="users.login" property="login"/> 
		<layout:collectionInput title="users.firstname" property="firstname" formProperty="firstname"/> 
		<layout:collectionInput title="users.firstname" property="lastname" formProperty="lastname"/> 
	</layout:collection> 
	... 
</layout:form> 
...
How can I make a column editable with mapped properties in the form ?

Now, we want to use mapped properties in the form instead of indexed properties. This way we don't have to worry about the order and numbers of the elements. This example suppose the firstname and lastname properties of the form bean are mapped properties. When processing the action, we will be able to get the new names of a user by specifying its login

...
<layout:form action="/updateUsernames"> 
	...
	<layout:collection name="users" styleClass="ARRAY"> 
	<layout:collectionItem title="users.login" property="login"/> 
	<layout:collectionInput title="users.firstname" property="firstname" formProperty="firstname" keyProperty="login"/> 
	<layout:collectionInput title="users.firstname" property="lastname" formProperty="lastname" keyProperty="login"/> 
	</layout:collection>
	... 
</layout:form>
...
How do I build an editable text/checkbox/radio/select/textarea column ?

The collectionInput tag allows to build only text input field, and is rather complicated to use. It's usually easier to use the usual <layout:text>, <layout:textarea>, <layout:select>, <layout:checkbox>, <layout:radio> tags. This requires to set the property of the tag with an EL :

			<layout:form action="/someAction">
				<layout:collection property="aCollectionInFheForm" indexId="index">
					<layout:collectionItem title="some.title">
						<layout:checkbox property="aCollectionIntheForm[${index}].aBooleanProperty" layout="false"/>
					</layout:collectionItem>
				</layout:collection>
			</layout:form>
		

In this example, the Struts form bean as a java.util.Collection property named "aCollectionInTheForm". This collection contains object which have a boolean property named "aBooleanProperty". The layout="false" attribute tells the checkox tag to not render title and HTML positionning code.

Data swap

Data swap
How can I swap data between two collections ?

Now we want to move users between two lists. We can do this with the swap tag

This example suppose:

  • There are two collections in the request scope, under the name "list1" and "list2" containing user objets having the properties username and fullname
  • The form bean associated with the swap action has two indexed properties named users1 and users2
...
<layout:form action="/swap.do" reqCode="displayResult">
	<layout:line>
		<layout:swap property="username,username" formProperty="users1,users2" selectedStyleClass="FORMSWAP">
			<layout:collection name="list1" styleClass="FORM" height="150" > 
				<layout:collectionItem title="Login" property="username"/> 
				<layout:collectionItem title="Name" property="fullName"/> 
			</layout:collection>
			<layout:collection name="list2" styleClass="FORM" height="150">
				<layout:collectionItem title="Login" property="username"/>
				<layout:collectionItem title="Name" property="fullName"/>
			</layout:collection> 
		</layout:swap>
		<layout:submit valign="top">Submit</layout:submit> 
	</layout:line> 
...

Here is a running example

Nested collection

Nested collection
How can I iterate over nested collections ?

The following code displays the list of mail account of a list of user

This example suppose:

  • The collection "v" contains "User" object.
  • "User" objects have a firstname, lastname and subscription properties
  • The getter of the subscription property returns a collection of mail account objects.
  • Mail account objects have a "host" property.
...
<layout:collection name="v" id="bean1" title="User" styleClass="FORM">
	<layout:collectionItem title="Name" name="bean1" property="lastname"/> 
	<layout:collectionItem title="Firstname" name="bean1" property="firstname"/>
	<layout:nestedCollection property="subscriptions" id="bean2"> 
		<layout:collectionItem title="Subscriptions" name="bean2" property="host"/> 
	</layout:nestedCollection>
</layout:collection>
... 

The result is viewable here.

Parallel iteration

Parallel iteration
How can I iterate over two collection at the same time ?

The struts-layout collection and news tag allow to iterate two collections at the same time. The following example shows how to do this.

<%@page import="java.util.Vector" %>
<%@taglib uri="/WEB-INF/struts-layout.tld" prefix="layout" %>
<% Vector v1 = new Vector();
   v1.add("item1");
   v1.add("item2");
   v1.add("item3");
   Vector v2 = new Vector();
   v2.add("5$");
   v2.add("3$");
   v2.add("9$");
   pageContext.setAttribute("v1", v1); pageContext.setAttribute("v2", v2);
%>
<html>
<head>
<link rel="stylesheet" href='../config/skin2.css' type="text/css">
</head>
<body>
<layout:collection name="v1" id="bean1" name2="v2"  id2="bean2" title="Item price" styleClass="FORM">
<layout:collectionItem title="Item" name="bean1"/>
<layout:collectionItem title="Price" name="bean2"/>
</layout:collection>
</body>
</html>

Result

Block iteration

Block iteration
How can I iterate over a collection and display each item in a different cell ?"

The <layout:table> tag makes it possible to iterate over a collection and to present the result in a table of a given number of columns. Here is an exemple:

<@page import="java.util.Vector"%>
<%@taglib uri="/WEB-INF/struts-layout.tld" prefix="layout" %>
<%@taglib uri="/WEB-INF/struts-bean.tld" prefix="bean" %>
<% Vector v = new Vector();
   v.add("This");
   v.add(" ");
   v.add("is");
   v.add(" ");
   v.add("a");
   v.add(" ");
   v.add("very");
   v.add(" ");
   v.add("simple");
   v.add(" ");
   v.add("example.");
   pageContext.setAttribute("v", v);
%>

<html>
<body>
	<layout:table name="v" id="mot" col="3">
		<bean:write name="mot"/>
	</layout:table>
</body>
</html>

Result

Master/detail

Master/detail
How can I create a simple master detail page ?
The <layout:collectionDetail> and <layout:detail> tags allow to create easily a master/detail page. Here is an example:
<layout:column>
	<layout:collection name="billets" model="green" id="billet" indexId="index">
		<layout:collectionItem title="liste.titre" property="titre" sortable="true"/>
		<layout:collectionItem title="liste.dossier" property="dossier" sortable="true"/>
		<layout:collectionItem title="liste.montant" property="montant" sortable="true" width="75"/>
		<layout:collectionDetail property="fournisseur"/>
		<layout:collectionDetail property="voyageur"/>
		<layout:collectionDetail property="factureClient"/>
	</layout:collection>		
	<layout:grid cols="3" styleClass="DETAILGRID">
		<layout:detail key="detail.fournisseur" property="fournisseur" styleClass="DETAIL"/>
		<layout:detail key="detail.voyageur" property="voyageur" styleClass="DETAIL"/>
		<layout:detail key="detail.facture" property="factureClient" styleClass="DETAIL"/>
	</layout:grid>
</layout:column>				
			

The titre, dossier and montant properties are displayed as columns, the fournisseur, voyageur and facture properties are displayed as details.

Statistics

Statistics
What should I do to configure statistics support in Struts-Layout ?

First, you need to put commons-math.jar from the Jakarta Commons project in your classpath. Second, and only if you have change the default collection renderer, you need to have your collection renderer implements the interface fr.improve.struts.taglib.layout.util.IMathCollectionRenderer.

Which operations are supported ?

The following operations are supported : geometricMean, max, mean, min, product, sum, sumLog, sumSq, variance

Scrolling

Scrolling
How do I enable scrolling ?

Simply set the width or height attribute to set the collection size onscreen. Scrollbars will appear automatically. Example :

...
<layout:collection name="users" title="Users" styleClass="SCROLL" height="200">					
	...
</layout:collection>
...
How can I fix the headers of a scrollable collection ?

Struts-Layout provides two specific renderers that can fix collection headers :

  • fr.improve.struts.taglib.layout.util.FixedHeaderCollection

    This renderer generates two tables, one for the header and one for the body. Javascript code synchronizes the size of the column of the two tables. The styleId attribute of the collection tag must be set when using this renderer.
  • fr.improve.struts.taglib.layout.renderer.FixedHeaderCollection

    For Mozilla, this renderer simply generates thead and tbody elements, which is enough for this browser. For Internet Explorer, this renderer sets the position of the header row with a CSS expression. This renderer works better than the one in the util package.

To use the renderers, you need to declare them in the Struts-Layout configuration file. Have a look at how to do this here You can seew the renderers in action here :

To get the examples source code, download the MailReader example application and check the examples/collectionScrollable.jsp and example/collectionScrollable2.jsp.