DataTable: Facets Bug
---------------------
Key: MYFACES-288
URL: http://issues.apache.org/jira/browse/MYFACES-288
Project: MyFaces
Type: Bug
Versions: 1.0.9 beta
Reporter: Mathias Werlitz
Priority: Blocker
There seems to be a big bug in the dataTable component implementation.
If you use two dataTable components within each other the facets of the inner
table do not work correctly.
For example if you use a inputText component in the footer (of the inner table)
the value is not updated an no valueChangeListener is notified.
Here an example:
<f:view>
<html>
<body>
<h:form>
<h:dataTable id="outer" value="#{test}" var="outeritem">
<h:column>
<h:dataTable id="inner" value="#{outeritem}" var="item" >
.....
<f:facet name="header">
<h:inputText id="myinput"
valueChangeListener="#{testBean.listener}" />
</f:facet>
</h:dataTable>
</h:column>
</h:dataTable>
</h:form>
</body>
</html>
</f:view>
I have found one solution, but I'm not sure if it is the right way:
The funkctions to save the childState for the nested UIData have to be fixed in
javax.faces.component.UIData:
private void restoreDescendantComponentStates(
FacesContext context,
UIComponent component,
boolean saveState)
{
for (Iterator i = component.getFacetsAndChildren();
i.hasNext();)
{
UIComponent child = (UIComponent) i.next();
//clear this descendant's clientId:
child.setId(child.getId());
//HACK: This assumes that setId always clears the
cached clientId. Can we be sure?
if (saveState)
{
//see saveDescendantComponentStates(UIComponent)
if (child instanceof UIData)
{
UIData childUIData = (UIData) child;
Object state =
_rowState._clientIdsToChildUIDataStates.get(
childUIData.getClientId(context));
if (state == null)
{
UIDataRowState initialState =
(UIDataRowState)
_rowState._clientIdsToChildUIDataStates.get(getInitialClientId(context, child));
if (initialState == null)
{
throw new
IllegalStateException(
"No initial
state defined for clientId: " + child.getClientId(context));
}
state = new
UIDataRowState(initialState);
}
childUIData._rowState =
(UIDataRowState) state;
childUIData.restoreDescendantComponentStates(context, childUIData, true); // fix
restoreDescendantComponentStates(context, component, false);
continue;
}
if (!_firstTimeRendered && child instanceof
EditableValueHolder)
{
EditableValueHolder childEVH =
(EditableValueHolder) child;
Object state =
_rowState._clientIdsToChildEVHStates.get(child.getClientId(context));
if (state == null)
{
state =
_rowState._clientIdsToChildEVHStates.get(
getInitialClientId(context, child));
}
((EditableValueHolderState)
state).restore(childEVH);
}
}
restoreDescendantComponentStates(context, child,
saveState);
}
}
private void saveDescendantComponentStates(FacesContext context, UIComponent
component)
{
for (Iterator i = component.getFacetsAndChildren();
i.hasNext();)
{
//TODO: what if child is an EditableValueHolder AND a
UIData?
UIComponent child = (UIComponent) i.next();
if (child instanceof UIData)
{
UIData childUIData = (UIData) child;
childUIData.saveDescendantComponentStates(context, childUIData); // fix
_rowState._clientIdsToChildUIDataStates.put(
childUIData.getClientId(context),
childUIData._rowState);
continue;
}
if (child instanceof EditableValueHolder)
{
EditableValueHolder childEVH =
(EditableValueHolder) child;
_rowState._clientIdsToChildEVHStates.put(
child.getClientId(context),
new EditableValueHolderState(childEVH));
}
saveDescendantComponentStates(context, child);
}
}
--
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
http://www.atlassian.com/software/jira