rich:datatable rowspan issue

∥☆過路亽.° 提交于 2019-12-03 12:38:53

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.

There's unfortunately no rowspan support in JSF UIData components. Best what you could do is to just display the collection of products in the same row. You can iterate over it using another UIData component such as h:dataTable (renders <table>), t:dataList (renders <ul>) or a4j:repeat (renders nothing, you need to use e.g. <br/> after each item).

Semi-pseudo based on the basic JSF components:

<h:dataTable value="#{bean.companies}" var="company">
    <h:column>
        <h:outputText value="#{company.name}" />
    </h:column>
    <h:column>
        <h:outputText value="#{company.email}" />
    </h:column>
    <h:column>
        <h:dataTable value="#{company.products}" var="product">
            <h:column>
                <h:outputText value="#{product.name}" />
            </h:column>
        </h:dataTable>
    </h:column>
    <h:column>
        <h:dataTable value="#{company.products}" var="product">
            <h:column>
                <h:outputText value="#{product.description}" />
            </h:column>
        </h:dataTable>
    </h:column>
</h:dataTable>

Use CSS the smart way so that it look like rowspans.

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>

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!