5 Replies Latest reply on Jan 15, 2010 3:57 AM by Markos Fragkakis

    Complex rich:dataTable

    Markos Fragkakis Newbie

      Hi all,

       

      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:

       

      Company Name

      Company Email

      Product Name

      Product Description

      Company A

      companyA@companyA.com

      ProductA 1

      Description A1

      Product A2

      Description A2

      Product A3

      DescriptionA 3

      Company B

      CompanyB@companyB.com

      ProductB 1

      Description B1

      Product B2

      Description B2

      Product B3

      Description B3

      Product B4

      DescriptionB 4

       

      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 psudocode for this?

       

      Cheers!

        • 1. Re: Complex rich:dataTable
          Markos Fragkakis Newbie

          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 <a4j:repeat> 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. 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?

           

          Cheers!

          • 2. Re: Complex rich:dataTable
            Markos Fragkakis Newbie

            The issue is probably related to this article [1], 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.

             

            [1] http://blog.hibernate.org/11633.lace

            • 3. Re: Complex rich:dataTable
              Ilya Shaikovsky Master

              Good catch!

              https://jira.jboss.org/jira/browse/RF-1870 will be moved to 4.x for implementation.

               

              Currently you could use only something like:

               

              <r:dataTable>

                   <r:column>

               

                   </r:column>

                   <r:column>

               

                   </r:column>

                   <r:column>

                        <r:dataTable>

                             <r:column>

               

                             </r:column>

                        </r:dataTable>

                   </r:column>

              </r:dataTable>

              but then nested table should has fixed cells sizes in order them to be in sync for different rows. And also outer table shoud define complex header with second table headers included.

              1 of 1 people found this helpful
              • 4. Re: Complex rich:dataTable
                Markos Fragkakis Newbie

                Thanks for the response Ilya!

                 

                Not having a rowspan would intriduce a new problem for me: I need the pagination to be based on the products, if I want to have a standard table size (otherwise my rows will refer to the Companes, some of which will have tens of products).

                 

                Any advice on that?

                • 5. Re: Complex rich:dataTable
                  Markos Fragkakis Newbie

                  OK, based on the last update, created the page doing the iterations using **c:forEach** (while building the component tree). The solution I am providing works, but something feels wrong about it because:

                   

                  - It takes too much time (~3 seconds 100% CPU for about 20 companies and 200 products). I suspect that this is because the for c:forEach loop essentially builds a huge component tree, which has to be rendered, instead of the initial approaches where the component tree was much smaller.
                  - I think I will have to re-build the whole component tree for every change in the data, instead of just re-rendering it.

                   

                  Anyways, to the code. What I did is something like this (have not tested the one below, but you will get the picture. Notice that the iteration inside the rich:dataTable is essentially ignored):

                   

                  <rich:dataTable width="70%" id="applicantsTable" rows="100"
                       rowClasses="applicant_row" columnClasses="col"
                       value="#{backingBean.companyList}" var="company">
                       <f:facet name="header">
                                 <rich:column>
                                      <h:outputText styleClass="headerText" value="Company Name" />
                                 </rich:column>
                                 <rich:column>
                                      <h:outputText styleClass="headerText" value="Company Email" />
                                 </rich:column>
                                 <rich:column>
                                      <h:outputText styleClass="headerText" value="Product Name" />
                                 </rich:column>
                                 <rich:column>
                                      <h:outputText styleClass="headerText" value="Product Email" />
                                 </rich:column>
                            
                       </f:facet>
                  
                       <c:forEach items="#{backingBean.companyList}" var="c_company">
                  
                            <c:if test="#{prs:collectionSize(c_company.products)> 0}">
                            
                                 <rich:column breakBefore="true"
                                      rowspan="#{prs:collectionSize(c_company.products)}">
                                      <h:outputText value="#{c_company.name}" />
                                 </rich:column>
                                 
                                 <rich:column
                                      rowspan="#{prs:collectionSize(c_company.products)}">
                                      <h:outputText value="#{c_company.email}" />
                                 </rich:column>
                  
                                 <c:forEach items="#{c_company.products}" var="c_product">
                                      <!-- This if clause is just to determine the breakBefore attribute -->
                                      <c:if test="#{c_company.products[0] == c_product}">
                                           <rich:column>
                                                <h:outputText value="#{c_product.name}" />
                                           </rich:column>
                                      </c:if>
                  
                                      <c:if test="#{c_company.products[0] != c_product}">
                                           <rich:column breakBefore="true" styleClass="internal_cell">
                                                <h:outputText value="#{c_product.name}" />
                                           </rich:column>
                                      </c:if>
                  
                                      <rich:column styleClass="internal_cell">
                                           <h:outputText value="#{c_product.email}" />
                                      </rich:column>
                  
                                 </c:forEach>
                  
                            </c:if>
                  
                       </c:forEach>
                  
                  
                  </rich:dataTable>