public class UIData extends UIComponentBase implements NamingContainer, UniqueIdVendor
UIData is a
UIComponent
that supports data binding to a collection of data objects represented by a DataModel
instance, which is the current value of this component itself (typically established via a ValueExpression
).
During iterative processing over the rows of data in the data model, the object for the current row is exposed as a
request attribute under the key specified by the var
property.
Only children of type UIColumn
should be processed by renderers associated with this component.
By default, the rendererType
property is set to jakarta.faces.Table
. This value can be
changed by calling the setRendererType()
method.
Modifier and Type | Field and Description |
---|---|
static java.lang.String |
COMPONENT_FAMILY
The standard component family for this component.
|
static java.lang.String |
COMPONENT_TYPE
The standard component type for this component.
|
ATTRS_WITH_DECLARED_DEFAULT_VALUES, BEANINFO_KEY, bindings, COMPOSITE_COMPONENT_TYPE_KEY, COMPOSITE_FACET_NAME, FACETS_KEY, VIEW_LOCATION_KEY
SEPARATOR_CHAR
Constructor and Description |
---|
UIData()
Create a new
UIData instance with default property values. |
Modifier and Type | Method and Description |
---|---|
void |
broadcast(FacesEvent event)
Override the default
UIComponentBase.broadcast(jakarta.faces.event.FacesEvent) processing to unwrap any wrapped FacesEvent and reset
the current row index, before the event is actually broadcast. |
java.lang.String |
createUniqueId(FacesContext context,
java.lang.String seed)
Generate an identifier for a component.
|
void |
encodeBegin(FacesContext context)
In addition to the default behavior, ensure that any saved per-row state for our child input components is discarded
unless it is needed to rerender the current page with errors.
|
java.lang.String |
getClientId(FacesContext context)
Return a client identifier for this component that includes the current value of the
rowIndex property,
if it is not set to -1. |
protected DataModel |
getDataModel()
Return the internal
DataModel object representing the data objects that we will iterate over in this
component's rendering. |
java.lang.String |
getFamily()
Return the identifier of the component family to which this component belongs. |
int |
getFirst()
Return the zero-relative row number of the first row to be displayed.
|
UIComponent |
getFooter()
Return the footer facet of this component (if any).
|
UIComponent |
getHeader()
Return the header facet of this component (if any).
|
int |
getRowCount()
Return the number of rows in the underlying data model.
|
java.lang.Object |
getRowData()
Return the data object representing the data for the currently selected row index, if any.
|
int |
getRowIndex()
Return the zero-relative index of the currently selected row.
|
int |
getRows()
Return the number of rows to be displayed, or zero for all remaining rows in the table.
|
java.lang.Object |
getValue()
Return the value of the UIData.
|
java.lang.String |
getVar()
Return the request-scope attribute under which the data object for the current row will be exposed when iterating.
|
boolean |
invokeOnComponent(FacesContext context,
java.lang.String clientId,
ContextCallback callback)
Override behavior from
UIComponentBase.invokeOnComponent(jakarta.faces.context.FacesContext, java.lang.String, jakarta.faces.component.ContextCallback) to provide special care for positioning the data
properly before finding the component and invoking the callback on it. |
boolean |
isRowAvailable()
Return a flag indicating whether there is
rowData available at the current rowIndex . |
boolean |
isRowStatePreserved()
Return the value of the |
void |
markInitialState()
Override the base class method to take special action if the method is being invoked when
|
void |
processDecodes(FacesContext context)
Override the default
UIComponentBase.processDecodes(jakarta.faces.context.FacesContext) processing to perform the following steps. |
void |
processUpdates(FacesContext context)
Override the default
UIComponentBase.processUpdates(jakarta.faces.context.FacesContext) processing to perform the following steps. |
void |
processValidators(FacesContext context)
Override the default |
void |
queueEvent(FacesEvent event)
Override the default
UIComponentBase.queueEvent(jakarta.faces.event.FacesEvent) processing to wrap any queued events in a wrapper so that we
can reset the current row index in broadcast() . |
void |
restoreState(FacesContext context,
java.lang.Object state)
Perform any processing required to restore the state from the entries
in the state Object.
|
java.lang.Object |
saveState(FacesContext context)
Gets the state of the instance as a
Serializable Object. |
protected void |
setDataModel(DataModel dataModel)
Set the internal DataModel.
|
void |
setFirst(int first)
Set the zero-relative row number of the first row to be displayed.
|
void |
setFooter(UIComponent footer)
Set the footer facet of this component.
|
void |
setHeader(UIComponent header)
Set the header facet of this component.
|
void |
setRowIndex(int rowIndex)
Set the zero relative index of the current row, or -1 to indicate that no
row is currently selected, by implementing the following algorithm.
|
void |
setRows(int rows)
Set the number of rows to be displayed, or zero for all remaining rows in the table.
|
void |
setRowStatePreserved(boolean preserveComponentState)
If this property is set to |
void |
setValue(java.lang.Object value)
Set the value of the
UIData . |
void |
setValueExpression(java.lang.String name,
ValueExpression binding)
Set the
ValueExpression used to calculate the value for the specified attribute or property name, if any. |
void |
setVar(java.lang.String var)
Set the request-scope attribute under which the data object for the current row wil be exposed when iterating.
|
boolean |
visitTree(VisitContext context,
VisitCallback callback)
Override the behavior in |
addClientBehavior, addFacesListener, clearInitialState, decode, encodeChildren, encodeEnd, findComponent, getAttributes, getChildCount, getChildren, getClientBehaviors, getDefaultEventName, getEventNames, getFacesContext, getFacesListeners, getFacet, getFacetCount, getFacets, getFacetsAndChildren, getId, getListenersForEventClass, getParent, getPassThroughAttributes, getRenderer, getRendererType, getRendersChildren, isRendered, isTransient, processRestoreState, processSaveState, removeFacesListener, restoreAttachedState, saveAttachedState, setId, setParent, setRendered, setRendererType, setTransient, subscribeToEvent, unsubscribeFromEvent
encodeAll, getClientId, getCompositeComponentParent, getContainerClientId, getCurrentComponent, getCurrentCompositeComponent, getNamingContainer, getPassThroughAttributes, getResourceBundleMap, getStateHelper, getStateHelper, getTransientStateHelper, getTransientStateHelper, getValueExpression, initialStateMarked, isCompositeComponent, isInView, isVisitable, popComponentFromEL, processEvent, pushComponentToEL, restoreTransientState, saveTransientState, setInView
public static final java.lang.String COMPONENT_TYPE
The standard component type for this component.
public static final java.lang.String COMPONENT_FAMILY
The standard component family for this component.
public UIData()
Create a new UIData
instance with default property values.
public java.lang.String getFamily()
UIComponent
Return the identifier of the component family to which this component belongs. This identifier, in conjunction with
the value of the rendererType
property, may be used to select the appropriate Renderer
for this
component instance. Note this method should NOT return null
getFamily
in class UIComponent
public int getFirst()
Return the zero-relative row number of the first row to be displayed.
public void setFirst(int first)
Set the zero-relative row number of the first row to be displayed.
first
- New first row numberjava.lang.IllegalArgumentException
- if first
is negativepublic UIComponent getFooter()
Return the footer facet of this component (if any). A convenience method for getFacet("footer")
.
public void setFooter(UIComponent footer)
Set the footer facet of this component. A convenience method for getFacets().put("footer", footer)
.
footer
- the new footer facetjava.lang.NullPointerException
- if footer
is null
public UIComponent getHeader()
Return the header facet of this component (if any). A convenience method for getFacet("header")
.
public void setHeader(UIComponent header)
Set the header facet of this component. A convenience method for getFacets().put("header", header)
.
header
- the new header facetjava.lang.NullPointerException
- if header
is null
public boolean isRowAvailable()
Return a flag indicating whether there is rowData
available at the current rowIndex
. If no
wrappedData
is available, return false
.
FacesException
- if an error occurs getting the row availabilitypublic int getRowCount()
Return the number of rows in the underlying data model. If the number of available rows is unknown, return -1.
FacesException
- if an error occurs getting the row countpublic java.lang.Object getRowData()
Return the data object representing the data for the currently selected row index, if any.
FacesException
- if an error occurs getting the row datajava.lang.IllegalArgumentException
- if now row data is available at the currently specified row indexpublic int getRowIndex()
Return the zero-relative index of the currently selected row. If we are not currently positioned on a row, return -1. This property is not enabled for value binding expressions.
FacesException
- if an error occurs getting the row indexpublic void setRowIndex(int rowIndex)
Set the zero relative index of the current row, or -1 to indicate that no
row is currently selected, by implementing the following algorithm. It is possible to set the row index at a value
for which the underlying data collection does not contain any row data. Therefore, callers may use the
isRowAvailable()
method to detect whether row data will be available for use by the
getRowData()
method.
To support transient state among descendents, please consult the specification for setRowStatePreserved(boolean)
,
which details the requirements for setRowIndex()
when the rowStatePreserved
JavaBeans
property is set to true
.
DataModel
associated with this UIData
instance.rowIndex
value is -1:
var
property is not null, remove the corresponding request scope attribute (if any).rowIndex
value is not -1:
var
property is not null, call getRowData()
and expose the resulting data object
as a request scope attribute whose key is the var
property value.
To save current state information for all descendant components, UIData
must maintain per-row information for
each descendant as follows:
EditableValueHolder
, save the state of its
localValue
property.EditableValueHolder
, save the state of the
localValueSet
property.EditableValueHolder
, save the state of the valid
property.EditableValueHolder
, save the state of the
submittedValue
property.
To restore current state information for all descendant components, UIData
must reference its previously
stored information for the current rowIndex
and call setters for each descendant as follows:
EditableValueHolder
, restore the value
property.EditableValueHolder
, restore the state of the
localValueSet
property.EditableValueHolder
, restore the state of the valid
property.EditableValueHolder
, restore the state of the
submittedValue
property.rowIndex
- The new row index value, or -1 for no associated rowFacesException
- if an error occurs setting the row indexjava.lang.IllegalArgumentException
- if rowIndex
is less than -1public int getRows()
Return the number of rows to be displayed, or zero for all remaining rows in the table. The default value of this property is zero.
public void setRows(int rows)
Set the number of rows to be displayed, or zero for all remaining rows in the table.
rows
- New number of rowsjava.lang.IllegalArgumentException
- if rows
is negativepublic java.lang.String getVar()
Return the request-scope attribute under which the data object for the current row will be exposed when iterating. This property is not enabled for value binding expressions.
public void setVar(java.lang.String var)
Set the request-scope attribute under which the data object for the current row wil be exposed when iterating.
var
- The new request-scope attribute namepublic boolean isRowStatePreserved()
Return the value of the rowStatePreserved
JavaBeans property. See setRowStatePreserved(boolean)
.
rowStatePreserved
.public void setRowStatePreserved(boolean preserveComponentState)
If this property is set to true
, the UIData
must take steps to ensure that modifications to
its iterated children will be preserved on a per-row basis. This allows applications to modify component properties,
such as the style-class, for a specific row, rather than having such modifications apply to all rows.
To accomplish this, UIData
must call StateHolder.saveState(jakarta.faces.context.FacesContext)
and
TransientStateHolder.saveTransientState(jakarta.faces.context.FacesContext)
on its children to capture their state on exiting each row. When
re-entering the row, StateHolder.restoreState(jakarta.faces.context.FacesContext, java.lang.Object)
and TransientStateHolder.restoreTransientState(jakarta.faces.context.FacesContext, java.lang.Object)
must be
called in order to reinitialize the children to the correct state for the new row. All of this action must take place
during the processing of setRowIndex(int)
.
Users should consider enabling this feature for cases where it is necessary to modify properties of
UIData
's children in a row-specific way. Note, however, that row-level state saving/restoring does add
overhead. As such, this feature should be used judiciously.
preserveComponentState
- the flag if the state should be preserved.public java.lang.Object getValue()
Return the value of the UIData. This value must either be be of type
DataModel
, or a type that can be adapted into a DataModel
. UIData
will automatically
adapt the following types:
java.util.List
java.sql.ResultSet
java.util.Collection
All other types will be adapted using the ScalarDataModel
class, which will treat the object as a single row
of data.
public void setValue(java.lang.Object value)
Set the value of the UIData
. This value must either be be of type DataModel
, or a type that can
be adapted into a DataModel
.
value
- the new valuepublic void setValueExpression(java.lang.String name, ValueExpression binding)
Set the ValueExpression
used to calculate the value for the specified attribute or property name, if any. In
addition, if a ValueExpression
is set for the value
property, remove any synthesized
DataModel
for the data previously bound to this component.
setValueExpression
in class UIComponent
name
- Name of the attribute or property for which to set a ValueExpression
binding
- The ValueExpression
to set, or null
to remove any currently set
ValueExpression
java.lang.IllegalArgumentException
- if name
is one of id
, parent
,
var
, or rowIndex
java.lang.NullPointerException
- if name
is null
public java.lang.String getClientId(FacesContext context)
Return a client identifier for this component that includes the current value of the rowIndex
property,
if it is not set to -1. This implies that multiple calls to getClientId()
may return different results,
but ensures that child components can themselves generate row-specific client identifiers (since UIData
is a
NamingContainer
).
getClientId
in class UIComponentBase
context
- The FacesContext
for the current requestjava.lang.NullPointerException
- if context
is null
public boolean invokeOnComponent(FacesContext context, java.lang.String clientId, ContextCallback callback) throws FacesException
Override behavior from UIComponentBase.invokeOnComponent(jakarta.faces.context.FacesContext, java.lang.String, jakarta.faces.component.ContextCallback)
to provide special care for positioning the data
properly before finding the component and invoking the callback on it. If the argument clientId
is equal
to this.getClientId()
simply invoke the contextCallback
, passing the context
argument and this as arguments, and return true.
If the argument clientId
is not
equal to this.getClientId()
, inspect each of the facet children of this UIData
instance and
for each one, compare its clientId
with the argument clientId
. If there is a match, invoke
the contextCallback
, passing the context
argument and this as arguments, and return
true
. Otherwise, attempt to extract a rowIndex from the clientId
. For example, if the
argument clientId
was form:data:3:customerHeader
the rowIndex would be 3
. Let
this value be called newIndex
. The current rowIndex of this instance must be saved aside and restored
before returning in all cases, regardless of the outcome of the search or if any exceptions are thrown in the
process.
The implementation of this method must never return true
if setting the rowIndex of this instance to be
equal to newIndex
causes this instance to return false
from isRowAvailable()
.
invokeOnComponent
in class UIComponentBase
context
- the FacesContext
for the current requestclientId
- the client identifier of the component to be passed to the argument callback.callback
- an implementation of the Callback interface.true
if the a component with the given clientId
is found, the callback method was
successfully invoked passing that component as an argument, and no Exception was thrown. Returns false
if no component with the given clientId
is found.java.lang.NullPointerException
- if any of the arguments are nullFacesException
- if the argument Callback throws an Exception, it is wrapped in a FacesException
and re-thrown. Also throws FacesException
if any exception is thrown when deriving
the rowIndex from the argument clientId
.public void queueEvent(FacesEvent event)
Override the default UIComponentBase.queueEvent(jakarta.faces.event.FacesEvent)
processing to wrap any queued events in a wrapper so that we
can reset the current row index in broadcast()
.
queueEvent
in class UIComponentBase
event
- FacesEvent
to be queuedjava.lang.IllegalStateException
- if this component is not a descendant of a UIViewRoot
java.lang.NullPointerException
- if event
is null
public void broadcast(FacesEvent event) throws AbortProcessingException
Override the default UIComponentBase.broadcast(jakarta.faces.event.FacesEvent)
processing to unwrap any wrapped FacesEvent
and reset
the current row index, before the event is actually broadcast. For events that we did not wrap (in
queueEvent()
), default processing will occur.
broadcast
in class UIComponentBase
event
- The FacesEvent
to be broadcastAbortProcessingException
- Signal the Jakarta Faces implementation that no further processing on the
current event should be performedjava.lang.IllegalArgumentException
- if the implementation class of this FacesEvent
is not supported by this
componentjava.lang.NullPointerException
- if event
is null
public void encodeBegin(FacesContext context) throws java.io.IOException
In addition to the default behavior, ensure that any saved per-row state for our child input components is discarded unless it is needed to rerender the current page with errors.
encodeBegin
in class UIComponentBase
context
- FacesContext for the current requestjava.io.IOException
- if an input/output error occurs while renderingjava.lang.NullPointerException
- if context
is null
public void processDecodes(FacesContext context)
Override the default UIComponentBase.processDecodes(jakarta.faces.context.FacesContext)
processing to perform the following steps.
rendered
property of this UIComponent
is false
, skip further
processing.rowIndex
to -1.processDecodes()
method of all facets of this UIData
, in the order determined by a
call to getFacets().keySet().iterator()
.processDecodes()
method of all facets of the UIColumn
children of this
UIData
.first
and rows
properties), performing the following processing for each row:
rowIndex
to -1.decode()
method of this component.RuntimeException
is thrown during decode processing, call FacesContext.renderResponse()
and re-throw the exception.processDecodes
in class UIComponentBase
context
- FacesContext
for the current requestjava.lang.NullPointerException
- if context
is null
public void processValidators(FacesContext context)
Override the default UIComponentBase.processValidators(jakarta.faces.context.FacesContext)
processing to perform the following steps.
rendered
property of this UIComponent
is false
, skip further
processing.rowIndex
to -1.processValidators()
method of all facets of this UIData
, in the order determined by
a call to getFacets().keySet().iterator()
.processValidators()
method of all facets of the UIColumn
children of this
UIData
.first
and rows
properties), performing the following processing for each row:
rowIndex
to -1.processValidators
in class UIComponentBase
context
- FacesContext
for the current requestjava.lang.NullPointerException
- if context
is null
PreValidateEvent
,
PostValidateEvent
public void processUpdates(FacesContext context)
Override the default UIComponentBase.processUpdates(jakarta.faces.context.FacesContext)
processing to perform the following steps.
rendered
property of this UIComponent
is false
, skip further
processing.rowIndex
to -1.processUpdates()
method of all facets of this UIData
, in the order determined by a
call to getFacets().keySet().iterator()
.processUpdates()
method of all facets of the UIColumn
children of this
UIData
.first
and rows
properties), performing the following processing for each row:
rowIndex
to -1.processUpdates
in class UIComponentBase
context
- FacesContext
for the current requestjava.lang.NullPointerException
- if context
is null
public java.lang.String createUniqueId(FacesContext context, java.lang.String seed)
UniqueIdVendor
Generate an identifier for a component. The identifier will be prefixed with UNIQUE_ID_PREFIX, and will be unique within this component-container. Optionally, a unique seed value can be supplied by component creators which should be included in the generated unique id.
createUniqueId
in interface UniqueIdVendor
context
- FacesContextseed
- an optional seed value - e.g. based on the position of the component in the VDL-templatepublic boolean visitTree(VisitContext context, VisitCallback callback)
Override the behavior in UIComponent.visitTree(jakarta.faces.component.visit.VisitContext, jakarta.faces.component.visit.VisitCallback)
to handle
iteration correctly.
If the UIComponent.isVisitable(jakarta.faces.component.visit.VisitContext)
method of this instance returns false
, take no action and return.
Call UIComponent.pushComponentToEL(jakarta.faces.context.FacesContext, jakarta.faces.component.UIComponent)
and invoke the visit callback on this UIData
instance as
described in UIComponent.visitTree(jakarta.faces.component.visit.VisitContext, jakarta.faces.component.visit.VisitCallback)
. Let the result of the invoctaion be visitResult. If
visitResult is VisitResult.COMPLETE
, take no further action and return true
. Otherwise,
determine if we need to visit our children. The default implementation calls
VisitContext.getSubtreeIdsToVisit(jakarta.faces.component.UIComponent)
passing this
as the argument. If the result of that call is
non-empty, let doVisitChildren be true
. If doVisitChildren is true
and
visitResult is VisitResult.ACCEPT
, take the following action.
If this component has facets, call UIComponent.getFacets()
on this instance and invoke the
values()
method. For each UIComponent
in the returned Map
, call
UIComponent.visitTree(jakarta.faces.component.visit.VisitContext, jakarta.faces.component.visit.VisitCallback)
.
If this component has children, for each UIColumn
child:
Call VisitContext.invokeVisitCallback(jakarta.faces.component.UIComponent, jakarta.faces.component.visit.VisitCallback)
on that UIColumn
instance. If such a call returns
true
, terminate visiting and return true
from this method.
If the child UIColumn
has facets, call UIComponent.visitTree(jakarta.faces.component.visit.VisitContext, jakarta.faces.component.visit.VisitCallback)
on each one.
Take no action on non-UIColumn
children.
Save aside the result of a call to getRowIndex()
.
For each child component of this UIData
that is also an instance of UIColumn
,
Iterate over the rows.
Let rowsToProcess be the return from getRows()
.
Let rowIndex be the return from getFirst()
- 1.
While the number of rows processed is less than rowsToProcess, take the following actions.
Call setRowIndex(int)
, passing the current row index.
If isRowAvailable()
returns false
, take no further action and return false
.
Call UIComponent.visitTree(jakarta.faces.component.visit.VisitContext, jakarta.faces.component.visit.VisitCallback)
on each of the children of this UIColumn
instance.
Call UIComponent.popComponentFromEL(jakarta.faces.context.FacesContext)
and restore the saved row index with a call to setRowIndex(int)
.
Return false
to allow the visiting to continue.
visitTree
in class UIComponent
context
- the VisitContext
that provides context for performing the visit.callback
- the callback to be invoked for each node encountered in the visit.true
to indicate that the tree visit is complete (eg. all
components that need to be visited have been visited). This results in the tree visit being short-circuited such that
no more components are visited.java.lang.NullPointerException
- if any of the parameters are null
.VisitContext.invokeVisitCallback()
public void markInitialState()
Override the base class method to take special action if the method is being invoked when
StateManager.IS_BUILDING_INITIAL_STATE
is true and the rowStatePreserved
JavaBeans property for this instance is true
.
The additional action taken is to traverse the descendents and save their state without regard to any particular row value.
markInitialState
in interface PartialStateHolder
markInitialState
in class UIComponentBase
public void restoreState(FacesContext context, java.lang.Object state)
StateHolder
Perform any processing required to restore the state from the entries in the state Object.
If the class that implements this interface has references to instances that also implement StateHolder (such as a
UIComponent
with event handlers, validators, etc.) this method must call the StateHolder.restoreState(jakarta.faces.context.FacesContext, java.lang.Object)
method on all those instances as well.
If the state
argument is null
, take no action and return.
restoreState
in interface StateHolder
restoreState
in class UIComponentBase
context
- the Faces context.state
- the state.public java.lang.Object saveState(FacesContext context)
StateHolder
Gets the state of the instance as a Serializable
Object.
If the class that implements this interface has references to instances that implement StateHolder (such as a
UIComponent
with event handlers, validators, etc.) this method must call the StateHolder.saveState(jakarta.faces.context.FacesContext)
method
on all those instances as well. This method must not save the state of children and facets. That is
done via the StateManager
This method must not alter the state of the implementing object. In other words, after executing this code:
Object state = component.saveState(facesContext);
component
should be the same as before executing it.
The return from this method must be Serializable
saveState
in interface StateHolder
saveState
in class UIComponentBase
context
- the Faces context.protected DataModel getDataModel()
Return the internal DataModel
object representing the data objects that we will iterate over in this
component's rendering.
If the model has been cached by a previous call to setDataModel(jakarta.faces.model.DataModel)
, return it. Otherwise call
getValue()
. If the result is null, create an empty ListDataModel
and return it. If the result is an
instance of DataModel
, return it. Otherwise, adapt the result as described in getValue()
and return
it.
protected void setDataModel(DataModel dataModel)
Set the internal DataModel. This UIData
instance must use the given DataModel
as its internal
value representation from now until the next call to setDataModel
. If the given DataModel
is null
, the internal DataModel
must be reset in a manner so that the next call to
getDataModel()
causes lazy instantion of a newly refreshed DataModel
.
Subclasses might call this method if they either want to restore the internal DataModel
during the
Restore View phase or if they want to explicitly refresh the current DataModel
for the
Render Response phase.
dataModel
- the new DataModel
or null
to cause the model to be refreshed.