When you use an array, list, SQL result set, or JSTL result object for
the
value attribute of
h:dataTable, JSF wraps the object
in a model that extends the
javax.faces.model.DataModel class:
value Attribute |
JSF Model |
Array |
ArrayDataModel |
List |
ListDataModel |
Result Set |
ResultSetDataModel |
JSTL Result |
ResultDataModel |
In many cases you don't need to be aware of the underlying model.
This section describes two situations where you do:
- Rendering row numbers
- Sorting table rows
This section shows how to use data models to access row number
information when such information is not stored directly in your bean.
Suppose you want to render row numbers, like this:
but you are using an array to hold the table data and the array does
not have row number information stored:
private static final Name[] names = new Name[] {
new Name("William", "Dupont"),
new Name("Anna", "Keeney"),
new Name("Mariko", "Randor"),
new Name("John", "Wilson")
};
The
ArrayDataModel class has
a
getRowIndex() method.
So wrap the
names object in an
ArrayDataModel object:
private DataModel<Name> model = new ArrayDataModel<Name>(names);
public DataModel<Name> getNames() { return model; }
and use the model as a value for the data table:
<h:dataTable value="#{tableData.names}" var="name">
<h:column>#{tableData.names.rowIndex + 1}</h:column>
<h:column>#{name.last},</h:column>
<h:column>#{name.first}</h:column>
</h:dataTable>
Possible drawback: this solution ties your managed bean to the JSF API.
If you want to efficiently sort a displayed data table, perhaps in
response to a user action, you can't just sort the array, list,
(cached) result set, or JSTL result object in your bean.
Instead, you should:
- Wrap your bean in an appropriate DataModel class,
- Create a class that extends DataModel and provides
sorting capability, and
- Give the h:dataTable tag an object of the extended type
This section describes one way to do this.
Note that future versions of JSF may include this capability.
When sorting data models we don't want to sort the underlying data
itself.
Instead, we sort a list of integers that index the data, leaving the
data itself alone.
For example, here is an array of name objects, where the array is
sorted by first name:
Suppose a user wants to display the table sorted by last name.
It would be inefficient to sort the array itself:
Instead, we maintain an array of indexes into the name array that parallels
the name array and gives the order that should be presented in the
displayed table.
When the table is first presented (sorted by first name), the arrays of
indexes and names look like:
After the user has requested a sort by last name, the arrays of
indexes and names look like:
Note that the array itself is unaffected.
When a data model accesses a row for display, it:
- Calls the model's setRowIndex method with the index of the
row currently being shown, then
- Gets the row data at that index
If you want a data model to use the order stored in the index array
rather than the actual indexes of the name array, you must intercept
calls to the
setRowIndex() method and substitute your values.
To do this, extend the
DataModel class with
a
SortFilterModel class that overrides
setRowIndex:
The
sorting example application shows how this can be done.