Description
The MyFacesDataTable extends the standard JSF DataTable by two important features:
- Possiblity to save the state of the DataModel.
- Support for clickable sort headers (see SortHeader component).
Extended data_table that adds some additional features to the standard data_table action: see attribute descriptions for preserveDataModel, sortColumn, sortAscending and preserveSort.
API
component-family | javax.faces.Data |
renderer-type | org.apache.myfaces.Table |
component-class | org.apache.myfaces.component.html.ext.HtmlDataTable |
renderer-class | org.apache.myfaces.renderkit.html.ext.HtmlTableRenderer |
tag-class | org.apache.myfaces.taglib.html.ext.HtmlDataTableTag |
Usage
<t:dataTable [ all standard dataTable attributes allowed ] [ preserveDataModel="{true|false}" ] [ preserveRowStates="{true|false}" ] [ forceIdIndexFormula="value-binding" ] [ sortColumn="value-binding" ] [ sortAscending="value-binding" ] [ preserveSort="{true|false}" ] [ renderedIfEmpty="{true|false}" ] [ rowIndexVar="variable name" ] [ rowCountVar="variable name" ] [ previousRowDataVar="variable name" ] [ rowId="value-binding" ] [ newspaperColumns="value-binding" ] [ newspaperOrientation="value-binding" ] [ rowStyleClass="css styleclass" ] [ rowStyle="inline css style" ] [ rowOnClick="javascript" ] [ rowOnDblClick="javascript" ] [ rowOnMouseDown="javascript" ] [ rowOnMouseUp="javascript" ] [ rowOnMouseOver="javascript" ] [ rowOnMouseMove="javascript" ] [ rowOnMouseOut="javascript" ] [ rowOnKeyPress="javascript" ] [ rowOnKeyDown="javascript" ] [ rowOnKeyUp="javascript" ]> standard dataTable body (<h:column> tags and optional "header", "footer", and "spacer" facets) <t:column> <t:columns> <t:command_sortheader/> inside column header or footer <t:dataTable>
Syntax
<t:dataTable>
all standard dataTable attributes allowed
preserveDataModel="{true|false}"
- Indicates whether the state for each row should not be discarded before the datatable is rendered again. Setting this to true might be hepful if an input component inside the datatable has no valuebinding and the value entered in there should be displayed again, or if the input component model is not updated. For example, during validation failure, immediate flag short-circuiting, or subForms. This will only work reliable if the datamodel of the datatable did not change either by sorting, removing or inserting rows. You can use HtmlDataTable.clearRowStates() or HtmlDataTable.deleteRowStateForRow(int deletedIndex) to programically modify the saved row states. Default: false
preserveRowStates="{true|false}"
forceIdIndexFormula="value-binding"
sortColumn="value-binding"
sortAscending="value-binding"
preserveSort="{true|false}"
renderedIfEmpty="{true|false}"
- Indicates whether this table should be rendered if the underlying DataModel is empty.
rowIndexVar="variable name"
- A parameter name, under which the current rowIndex is set in request scope similar to the var parameter.
rowCountVar="variable name"
- A parameter name, under which the rowCount is set in request scope similar to the var parameter.
previousRowDataVar="variable name"
- A parameter name, under which the previous RowData Object is set in request scope similar to the rowIndexVar and rowCountVar parameters.
rowId="value-binding"
- The id to use for <tr> elements that are generated by the table.
newspaperColumns="value-binding"
- The number of layout columns to wrap the table through.
newspaperOrientation="value-binding"
- The orientation of the columns in the table.
rowStyleClass="css style class"
- the style class to use for <tr> elements that are generated by the table. Can be a value-binding to assign row-data specific style classes
rowStyle="inline css style"
- inline style to use for <tr> elements that are generated by the table. Can be a value-binding to assign row-data specific style
Each event handler must evaluate to a javascript code which is executed on the client side. The event handler are used for the <tr> tag of the row.
You can use value-bindings for row specific event handler.
rowOnClick="javascript"
rowOnDblClick="javascript"
rowOnMouseDown="javascript"
rowOnMouseUp="javascript"
rowOnMouseOver="javascript"
rowOnMouseMove="javascript"
rowOnMouseOut="javascript"
rowOnKeyPress="javascript"
rowOnKeyDown="javascript"
rowOnKeyUp="javascript"
Instructions
Saving the state of the DataModel - the preserveDataModel
attribute
When this attribute is "true", the data behind
the current DataModel is saved after the render response phase and
restored in the restore component tree phase.
Why and when use this feature?
Whenever you
use a DataModel backed by a database connection you could run into
problems, when the data in the database has changed since the last
request. All Lifecycle phases prior to the render response phase iterate
the DataModel and assume that the DataModel is unchanged since the last
request. At least the row count must not have changed, because all
children of UIData that are bound to the DataModel rely on it. But even
if you can assure that row count never changes, a change in the data can
have unintentional sideeffects.
Using the preserveDataModel
feature prevents such problems. The DataModel (to be more exact: the
currently visible part of the DataModel given by the first and the rows
attribute) is freezed right after rendering and you can be sure that all
lifecycle actions during the next request happen on exactly the same
data.
What data types are supported?
To be able to
save the state of the DataModel the row objects must be serializable.
All standard DataModel types are supported, except ResultSet, which will
follow in one of the next releases,
Is updating the model supported?
Yes. Just
make your bean property that is bound to the DataTable component
writable, i.e. give it a setter method.
Wrapping table layout -- the newspaperColumns attribute and
spacer facet
The newspaperColumns attribute allows a long,
narrow table to be wrapped so that it becomes a short, wide table. This
allows more information to be shown on a single screen. This is commonly
used to present checkboxes for a long list of items. Use the "spacer"
facet to specify a component displayed between layout columns. The
newspaperOrientation attribute specifies if the columns will be layed out
in a vertical or horizontal manner,
Example:
<t:dataTable newspaperColumns="3" value="#{addressBB.states}" newspaperOrientation="horizontal" var="state"> <f:facet name="spacer"> <f:verbatim>&#160;</f:verbatim> </f:facet> <h:column> <h:outputText value="#{state.abbr}"/> </h:column> <h:column> <h:outputText value="#{state.name}"/> </h:column> </t:dataTable>
Working with a changing data - the forceIdIndexFormula
attribute
The default table assumes that your backing
data collection is stable between 2 requests. This assumption can be
false in several cases: concurrent accesses, unstable backing data
collection order, ... If you have components within that table that
update your data, you will get unintended behaviors.
This
attribute is meant to fix that problem.
The table's components and
the backing data objects are linked by the table's components' ids. By
default the changing part of those ids is the row number. So if the
backing data positions in the list is changed between the 2 requests
(like an element inserted in the head of the list), you will update the
wrong element in the backing data's collection.
To fix this, you
can set the forceIdIndexFormula to an EL that will be unique and stable
for each row. That way, even if your backing data list changes between 2
requests, you always update the intended element in the list.
Example : <t:dataTable value="#{mailDAO.userInbox}"
var="email" forceIdIndexFormula="#{email.primaryKey}" ...> ...
Warning : make sure that the value-binding evaluates to a unique
value for each row.