rich:datatable rowspan issue

Markos Fragkakis picture Markos Fragkakis · Jan 8, 2010 · Viewed 9.9k times · Source

I need to create a rich:dataTable (or even extended) with the following features:

I have a class Company having a collection of Product objects. I want to show the following table:

alt text

I still have not figured out how to do this with a subtable (in all the examples I found the subTable has the exact same columns as the master table). Presumably, I need to play with rowspans in the first two columns, but I still have not found the way.

Could someone provide a pseudo-code for this?

Cheers!

UPDATE 1: I tried set the rowspan of the columns in the left as the size of the list or products, and then :

  • if the products is empty (no products for the company yet), I print two columns. I do this conditionally by setting their rendered attribute to #{myFuncs:sizeOf(company.products)}
  • If the products are >= 1 then I iterate over them with and inside that loop I insert two columns (one for product name and one for description), and for each product name column except the first one I set the breakBefore attribute to #{ !myFunc:firstProduct(company.products, product)}, which evaluates to true for all product names except the first one.

Unfortunately, this did not work for me, because the columns inside the a4j:repeat do not appear at all - not because of the rendered tag. The loop is correct because if I print standard text else, it appears.

Is there a way to achieve rowspan, or am I banging my head on the wall?

UPDATE 2: The issue is probably related to this article, indicating the differences between iteration components such as < a4j:repeat> and the tag < c:forEach>. The first takes place at rendering time, while the second one operates earlier, when JSF components are placed onto the component tree of the page.

I tried to get the rich:columns outside the a4j:repeat and they get rendered (of course, not as expected, but they do).

Answer

Damo picture Damo · Jan 18, 2010

You can do this without those complex forEachs. You just need to take advantage of subTable and the rowKeyVar.

For example:

<rich:dataTable
    value="#{backingBean.companyList}"
    rows="100"
    var="company">
    <f:facet name="header">
        <rich:columnGroup>
            <rich:column>Company Name</rich:column>
            <rich:column>Company Email</rich:column>
            <rich:column>Product Name</rich:column>
            <rich:column>Product Email</rich:column>
        </rich:columnGroup>
    </f:facet>
    <rich:subTable value="#{company.products}" var="product" rowKeyVar="rowKey">
        <rich:column rowspan="#{company.products.size()}" rendered="#{rowKey eq 0}">
            #{company.name}
        </rich:column>
        <rich:column rowspan="#{company.products.size()}" rendered="#{rowKey eq 0}">
            #{company.email}
        </rich:column>
        <rich:column>
            #{product.name}
        </rich:column>
        <rich:column>
            #{product.email}
        </rich:column>
    </rich:subTable>
</rich:dataTable>

Renders perfectly for me. Note that I'm using Seam which has Jboss Extended EL that allows me to call size() on the collection. If you aren't using this you can use that prs:collectionSize() or fn:length() as a substitute.

This also works nicely with the Richfaces datascroller.

Hope this helps.

D.