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.