External Paging and Sorting

The default behavior of displaytag is working with a full list, handling sorting and paging trasparently. Sometimes, however, you could need to give displaytag only the records displayed, handling sorting and paging by yourself (this is what we call "partial list support").

Displaytag 1.1 offers two alternative ways for working with partial lists:

  • the first one uses the valuelist pattern, and requires that the object that you give to displaytag implements the org.displaytag.pagination.PaginatedList interface. You can pass this object to displaytag as an usual list, and it will extract paging and sorting information from it. This way is more recommended if you have to build your backend layer and you can easily follow this pattern.
  • a second way, recommended if you only have to use partial list for few tables that show a performance problem using full lists, is passing all the needed parameters as separate tag attributes (recors to be shown, page number, total number of records...)

Using the Valuelist pattern

If the object passed to the displaytag as a list is in fact an instance of org.displaytag.pagination.PaginatedList (and not a collection), displaytag will assume that the list is externally sorted and paginated. Implementing this interface is trivial, and an adapter over existing classes can easily be written. See the org.displaytag.pagination.PaginatedList javadocs for more details.

In order for the generated pagination and sort links to be "understandable" by the application, they are not generated the same way as for a traditional DisplayTag table. Indeed, since the table is externally sorted and paginated, the application must be able to easily get the sort and pagination parameters, without having to decode the DisplayTag encoded parameters.

These sort and pagination links are generated based on additional properties. These properties can be overridden using <display:setProperty/>, in order to be able to have different sort of page parameters in the application, or to have multiple tables in a single HTML page.

If the default values of these properties are used, the href of the sort links will look like this:

  http://foo.bar.com/context/requestUri?sort=name&dir=asc&originalParameters=originalValues.

The href of the pagination links will look like this:

  http://foo.bar.com/context/requestUri?sort=name&dir=asc&page=5&originalParameters=originalValues

Without implementing the PaginatedList interface

External sort

<display:table name="testList" sort="external" defaultsort="1" id="element">
  <display:column property="id" title="ID" sortable="true" sortName="id" />
  <display:column property="firstName" sortable="true" sortName="firstName" title="First Name" />
  <display:column property="lastName" sortable="true" sortName="lastName" title="Last Name" />
  <display:column property="address" sortable="true" sortName="address" title="Email Address"/>
</display:table>

When using the sort="external" property you are telling DisplayTag that your list is already sorted according to some specific column before the tag gets it. This is a must when used with partial lists as we will see below, however you can use it by itself. A new property named sortName has been addeed to the column tag. The purpose of this property is for convenience when writing the backend code that actually does the sorting of the data. For example the header link for the column with property id in the sample code above will render a link containing d-(encoded table id)-s=id. If you remove the sortName property from the column the link will instead contain d-(encoded table id)-s=0, which is the index of the column rather than the name. Once again it is solely for convenience.

The first time you access a jsp with a DisplayTag in it, there are two ways for the tag to know how your data is sorted. Firstly it will check for a request parameter d-(encoded table id)-s. If that parameter exists, and its value matches the sortName of one of the declared column tags, then when it is rendered to html it will set the matching column as being sorted. If that parameter does not exist it will examine the defaultsort property of the table tag, if it exists then it will render the corresponding column as sorted. Otherwise no column will be rendered as being sorted. So really you have two options. Set your backend to sort your data based on a set column when there is no request parameter, and set your defaultsort parameter to match that column. Or ensure that all links pointing to your page that houses the DisplayTag have a d-(encoded table id)-s=(column index or sortName) parameter in them.

To determine the request parameter name for column sorting you can do:

   new ParamEncoder(tableId).encodeParameterName(TableTagParameters.PARAMETER_SORT))

To get the order (ASC/DESC):

   new ParamEncoder(tableId).encodeParameterName(TableTagParameters.PARAMETER_ORDER))

Descending is 2, Ascending is 1.

External Sorting And Paging (Partial Lists)

<display:table name="testList" sort="external" defaultsort="1" pagesize="20" id="element" partialList="true" size="resultSize">
  <display:column property="id" title="ID" sortable="true" sortName="id" />
  <display:column property="firstName" sortable="true" sortName="firstName" title="First Name" />
  <display:column property="lastName" sortable="true" sortName="lastName" title="Last Name" />
  <display:column property="address" sortable="true" sortName="address" title="Email Address"/>
</display:table>

All of the above information for external sorting applies to partial lists. Additionally there are two new properties on the table tag: partialList and size. To enable partial lists simply set partialList="true" on the table tag. Next you must tell Display Tag the total size of your list since you are only making a specific subset of it available to the tag. You do this by storing the total list size in a java.lang.Integer object and putting it into some scope available to DisplayTag. Then you set size=(name the Integer was stored under) on the table tag. Very easy. It is also important that you specify a pagesize on the table tag. It is also a good idea to set your backend to load a default amount of your list when there are no request parameters, probably the first page worth of data.

To determine the starting record you need to return based on the request parameters provided via Display Tag you can do:

   (Integer.parseInt(request.getParameter((new ParamEncoder(tableId).encodeParameterName(TableTagParameters.PARAMETER_PAGE)))) - 1) * pageSize.

To get the ending record just add pageSize to the above value.