[
https://issues.jboss.org/browse/RF-11090?page=com.atlassian.jira.plugin.s...
]
Val Blant commented on RF-11090:
--------------------------------
Daniel, I do have 3 levels of _collapsibleSubTable_ nesting, but I avoided the problem you
are having by not using the _collapsibleSubTableToggler_ (b/c it doesn't work).
Instead, I made my own composite component for toggling the sub-tables, which was much
easier than fixing the renderer code.
If you are willing to settle for ajax refreshing the top-level dataTable on each
collapse/expand operation, then you can do something similar to my solution.
{code}
<rich:dataTable id="performanceIndicatorsTable"
value="#{registeredBackingBean.thematicAreas}" var="thematicArea">
<rich:column>
<agr-comp:toggleTwistie
action="#{registeredBackingBean.toggleRenderedRowAction}"
openCondition="#{registeredBackingBean.renderThematicAreaRow}"
render="performanceIndicatorsTable" />
<h:outputText value="#{thematicArea.thematicAreaNumber}"/>
</rich:column>
... more columns here ...
<rich:collapsibleSubTable
expanded="#{registeredBackingBean.renderThematicAreaRow}"
value="#{thematicArea.programs}" var="designatedProgram">
<rich:column>
<agr-comp:toggleTwistie
action="#{registeredBackingBean.toggleRenderedProgramRowAction(designatedProgram)}"
openCondition="#{registeredBackingBean.getRenderProgramRow(designatedProgram)}"
render="performanceIndicatorsTable" />
<h:outputText value="#{designatedProgram.programNum}" />
</rich:column>
<rich:collapsibleSubTable
expanded="#{registeredBackingBean.getRenderProgramRow(designatedProgram)}"
value="#{designatedProgram.performanceIndicators}"
var="performanceIndicator">
<rich:column>
<agr-comp:toggleTwistie
action="#{registeredBackingBean.toggleRenderedIndictorRowAction(performanceIndicator)}"
openCondition="#{registeredBackingBean.getRenderIndicatorRow(performanceIndicator)}"
render="performanceIndicatorsTable" />
</rich:column>
... etc ...
</rich:collapsibleSubTable>
</rich:collapsibleSubTable>
</rich:dataTable>
{code}
{code:title=toggleTwistie.xhtml}
<composite:interface>
<composite:attribute name="openCondition" required="true" />
<composite:attribute name="closedCondition" default="#{not
cc.attrs.openCondition}" />
<composite:attribute name="render" required="true" />
<composite:attribute name="execute" default="@region" />
<composite:attribute name="action"
method-signature="void action()"
required="true" />
</composite:interface>
<composite:implementation>
<agr-comp:closedTwistie
render="#{cc.attrs.render}"
action="#{cc.attrs.action}"
renderTwistie="#{cc.attrs.closedCondition}" />
<agr-comp:openTwistie
render="#{cc.attrs.render}"
action="#{cc.attrs.action}"
renderTwistie="#{cc.attrs.openCondition}" />
</composite:implementation>
{code}
{code:title=closedTwistie.xhtml}
<composite:interface>
<composite:attribute name="render" required="true" />
<composite:attribute name="renderTwistie" default="true" />
<composite:attribute name="execute" default="@region" />
<composite:attribute name="action"
method-signature="void action()"
targets="closedTwistieLink"
required="true" />
</composite:interface>
<composite:implementation>
<a4j:commandButton id="closedTwistieLink"
image="/images/down1.gif"
rendered="#{cc.attrs.renderTwistie}"
render="#{cc.attrs.render}"
execute="#{cc.attrs.execute}"
immediate="true"
limitRender="true"
alt='#{msgs["button.label.close"]}'/>
</composite:implementation>
{code}
{code:title=openTwistie.xhtml}
<composite:interface>
<composite:attribute name="render" required="true" />
<composite:attribute name="renderTwistie" default="true" />
<composite:attribute name="execute" default="@region" />
<composite:attribute name="action"
method-signature="void action()"
targets="openTwistieLink"
required="true" />
</composite:interface>
<composite:implementation>
<a4j:commandButton id="openTwistieLink"
image="/images/down.gif"
rendered="#{cc.attrs.renderTwistie}"
render="#{cc.attrs.render}"
execute="#{cc.attrs.execute}"
immediate="true"
limitRender="true"
alt='#{msgs["button.label.close"]}'/>
</composite:implementation>
{code}
I know it's messy, but I plan to switch to _collapsibleSubTableToggler_ in 4.1.0.Final
once it comes out.
rich:collapsibleSubTable cannot be nested
-----------------------------------------
Key: RF-11090
URL:
https://issues.jboss.org/browse/RF-11090
Project: RichFaces
Issue Type: Bug
Security Level: Public(Everyone can see)
Components: component-tables
Affects Versions: 4.0.0.Final
Reporter: Val Blant
Fix For: 4.1.0.Final
When _<rich:collapsibleSubTable />_ s are nested, the following error occurs:
{quote}
This page contains the following errors:
error on line 202 at column 74: Opening and ending tag mismatch: tbody line 0 and tr
Below is a rendering of the page up to the first error.
{quote}
The page is rendered up to the nested _<rich:collapsibleSubTable />_.
This error happens b/c nested sub tables render an extra _</tr>_ element after the
nested subtable row.
I was able to work around the problem by making a small tweak to
_CollapsibleSubTableRenderer_. The lines I added or changes are marked with *"// fix
line"* comment.
{code:title=FixedCollapsibleSubTableRenderer.java|borderStyle=solid}
/**
* Allows nested subTables to be rendered properly
*/
@ResourceDependencies({
@ResourceDependency(name = "jquery.js"),
@ResourceDependency(name = "richfaces.js"),
@ResourceDependency(library="org.richfaces", name =
"collapsible-subtable.ecss"),
@ResourceDependency(library="org.richfaces", name =
"collapsible-subtable.js")
})
public class FixedCollapsibleSubTableRenderer extends CollapsibleSubTableRenderer {
@Override
public void encodeRow(ResponseWriter writer, FacesContext facesContext, RowHolderBase
holder) throws IOException {
RowHolder rowHolder = (RowHolder)holder;
Row row = rowHolder.getRow();
putRowStylesIntoContext(facesContext, rowHolder);
rowHolder.setRowStart(true);
Iterator<UIComponent> components = row.columns();
if (rowHolder.isUpdatePartial()) {
partialStart(facesContext,((AbstractCollapsibleSubTable)
row).getRelativeClientId(facesContext) + ":b");
}
int columnNumber = 0;
boolean isSubtable = false; // fix line
while (components.hasNext()) {
UIComponent component = components.next();
if(component.isRendered()) {
if(component instanceof UIColumn ) {
component.getAttributes().put(COLUMN_CLASS, getColumnClass(rowHolder,
columnNumber));
encodeColumn(facesContext, writer, (UIColumn)component , rowHolder);
columnNumber++;
} else if (component instanceof AbstractCollapsibleSubTable) {
if(component.isRendered()) {
isSubtable = true; // fix line
encodeRowEnd(writer);
}
if ( ((AbstractCollapsibleSubTable) component).isExpanded() ) {
component.encodeAll(facesContext);
}
rowHolder.setRowStart(true);
}
}
}
if ( !isSubtable) encodeRowEnd(writer); // fix line
if (rowHolder.isUpdatePartial()) {
partialEnd(facesContext);
}
}
}
{code}
This renderer needs to be registered in _faces-config.xml_:
{code}
<render-kit>
<renderer>
<component-family>org.richfaces.Data</component-family>
<renderer-type>org.richfaces.CollapsibleSubTableRenderer</renderer-type>
<renderer-class>bla.FixedCollapsibleSubTableRenderer</renderer-class>
</renderer>
</render-kit>
{code}
--
This message is automatically generated by JIRA.
For more information on JIRA, see:
http://www.atlassian.com/software/jira