jsfdatatableprimefacesnested-lists

Iterate through nested List of Objects in p:dataTable


In Primefaces 5.1 (Tomcat 8 and Servlet 3.0) you can iterate through List<Objects> using DataGrid, DataList, DataTable etc.. for instance:

<p:dataTable var="car" value="#{dtBasicView.cars}">
  <p:column headerText="Id">
    <h:outputText value="#{car.id}" />
  </p:column>
</p:dataTable>

Controller:

@ManagedBean(name="dtBasicView")
@ViewScoped
public class BasicView implements Serializable {

  private List<Car> cars;

  @ManagedProperty("#{carService}")
  private CarService service;

  @PostConstruct
  public void init() {
      cars = service.createCars(10);
  }

  public List<Car> getCars() {
      return cars;
  }

  public void setService(CarService service) {
      this.service = service;
  }
}

But say the Car object has a property like washes so that when I do:

<h:outputText value="#{car.washes}" />

Inside the dataTable it returns a list of List<Washes>. I can not select the index so how do I iterate though the List<Washes> inside the dataTable?

I know I could create a dataGrid inside the data table and then do the same as with the cars to iterate through the list of Washes. But this creates a new "HTML table with a border inside one of the cells". How can I just iterate though the list and output the string from washes: #{washes.foo}


Update: I get this error when trying to use <ui:repeat> as per the answer:

Property 'foo' not found on type org.hibernate.collection.internal.PersistentSet

When I use <p:dataGrid> instead of <ui:repeat> it works.

Also, I was returning a set instead of a list so I had to use toArray()


Solution

  • You can just nest another iterating component like as you can nest a for loop in plain Java.

    Here's an example nesting another <p:dataTable>, assuming that Wash has a property foo:

    <p:dataTable value="#{bean.cars}" var="car">
      <p:column headerText="Washes">
        <p:dataTable value="#{car.washes}" var="wash">
          <p:column headerText="Foo">#{wash.foo}</p:column>
        </p:dataTable>
      </p:column>
    </p:dataTable>
    

    Use <ui:repeat> or perhaps <h:dataTable> if you want markupless/styleless iteration:

    <p:dataTable value="#{bean.cars}" var="car">
      <p:column headerText="Washes">
        <ui:repeat value="#{car.washes}" var="wash">
          #{wash.foo}
        </ui:repeat>
      </p:column>
    </p:dataTable>
    

    It's by the way strange to use a plural as class name while you can have multiple of them in a List. You might want to rename Washes to Wash. The above code snippets have already taken this into account. You see that the code becomes more self-documenting this way.


    Update as per your error; the <ui:repeat> and <h:dataTable> components doesn't support iterating over a Set<E>. The support will come in future JSF 2.3 version. If it's not an option to replace Set<E> by a List<E>, then just get an array out of it as below:

    <ui:repeat value="#{car.washes.toArray()}" ...>