rich faces rich:dataTable missing rows with child rich:dataTable
hindsp Feb 6, 2013 6:09 AMI have found that when rich:dataTable objects get nested, the rows in one of the first sub-tables do not get rendered on the resulting webpage. Has anybody found this before or can anybody suggest a solution?
I have created a dummy jsf page and backing bean that demonstrates my problem. Apologies if this is a long post but I think I'm better off giving proper detail.
In the example I created 4 nested datatables (see jsf below), where each datatable is used to display an object in the following hierarchy:
Farm
--Field
--Animal
--Tag
Each item in the hierarchy has three children (so each farm has 3 fields, each field has 3 animals and each animal has 3 tags). Given the code below, I would expect the tables to be displayed as follows:
farm1
--field1
--animal1
--tag1
--tag2
--tag3
--animal2
--tag4
--tag5
--tag6
--animal3
--tag7
--tag8
--tag9
--field2
--animal4
--tag10
--tag11
--tag12
--animal5
--tag13
--tag14
--tag15
--animal6
--tag16
--tag17
--tag18
--field3
--animal7
etc.
etc.
However, what is actually rendered is the following (i.e. the animals in field1 are not listed):
farm1
--field1 (the animals are not listed for this field)
--field2
--animal4
--tag10
--tag11
--tag12
--animal5
--tag13
--tag14
--tag15
--animal6
--tag16
--tag17
--tag18
--field3
--animal7
etc.
I can see from the debug that the backing bean has the correct data so I don't think it's a data issue.
If I remove the last nested dataTable from the jsf page (marked 'TROUBLESOME TABLE' in the jsf below), then it will render correctly. For example it will display as:
farm1
--field1
--animal1
--animal2
--animal3
--field2
--animal4
--animal5
--animal6
--field3
--animal7
etc.
The jsf page looks like this:
{code:xml}<ui:define name="body">
<a4j:form id="coOpForm">
<rich:dataTable id="farmsTable" value="#{coOpBean.farms}" var="farmVar" width="100%">
<rich:column>
<f:facet name="header">Farm Name</f:facet>
<h:outputText value="#{farmVar.name}" />
</rich:column>
<rich:column breakBefore="true" colspan="2">
<rich:dataTable id="fieldsTable" var="fieldVar" value="#{farmVar.fields}" width="50%">
<rich:column>
<f:facet name="header">Fields in #{farmVar.name}</f:facet>
<h:outputText value="#{fieldVar.fieldName}" />
</rich:column>
<rich:column breakBefore="true" colspan="3">
<rich:dataTable id="animalsTable" var="animalVar" value="#{fieldVar.animals}" width="50%">
<rich:column>
<f:facet name="header">Animals in #{fieldVar.fieldName} in #{farmVar.name}</f:facet>
<h:outputText value="#{animalVar.name}" />
</rich:column>
<!-- START OF TROUBLESOME TABLE -->
<rich:column breakBefore="true" colspan="4">
<rich:dataTable id="tagsTable" var="tagVar" value="#{animalVar.tags}" width="50%">
<rich:column>
<f:facet name="header">Tags for #{animalVar.name} in #{fieldVar.fieldName} in #{farmVar.name}</f:facet>
<h:outputText value="#{tagVar.code}" />
</rich:column>
</rich:dataTable>
</rich:column>
<!-- END OF TROUBLESOME TABLE -->
</rich:dataTable>
</rich:column>
</rich:dataTable>
</rich:column>
</rich:dataTable>
</a4j:form>
</ui:define>
{code}
The backing bean and associated classes look like this:
CoOpBean.java:
{code}
@Component("coOpBean")
@Scope(WebApplicationContext.SCOPE_SESSION)
public class CoOpBean {
private static final Log logger = LogFactory.getLog(CoOpBean.class);
List<Farm> farms;
String name;
/**
* @return the farms
*/
public List<Farm> getFarms() {
return farms;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param farms the farms to set
*/
public void setFarms(List<Farm> farms) {
this.farms = farms;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
{code}
Farm.java:
{code}
public class Farm {
private static int counter = 1;
private final String name;
private final List<Field> fields;
public Farm(){
name = "farm" + counter++;
fields = new ArrayList<Field>();
for (int i = 0; i < 3; i++){
fields.add(new Field());
}
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the fields
*/
public List<Field> getFields() {
return fields;
}
}
{code}
Field.java:
{code}
public class Field {
private static int counter = 1;
private String fieldName;
private List<Animal> animals;
public Field(){
fieldName = "field" + counter++;
animals = new ArrayList<Animal>();
for (int i = 0; i < 3; i++){
animals.add(new Animal());
}
}
/**
* @return the fieldName
*/
public String getFieldName() {
return fieldName;
}
/**
* @return the animals
*/
public List<Animal> getAnimals() {
return animals;
}
}
{code}
Animal.java:
{code}
public class Animal {
private static int counter = 1;
private final String name;
private final List<Tag> tags;
public Animal(){
name = "animal" + counter++;
tags = new ArrayList<Tag>();
for (int i = 0; i < 3; i++){
tags.add(new Tag());
}
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @return the tags
*/
public List<Tag> getTags() {
return tags;
}
}
{code}
Tag.java:
{code}
public class Tag {
private static int counter = 1;
/**
* @param code
*/
public Tag() {
super();
this.code = "tag" + counter++;
}
private final String code;
/**
* @return the code
*/
public String getCode() {
return code;
}
}
{code}