简体   繁体   English

rich:datatable rowspan问题

[英]rich:datatable rowspan issue

I need to create a rich:dataTable (or even extended) with the following features: 我需要创建一个富:dataTable(甚至扩展),具有以下功能:

I have a class Company having a collection of Product objects. 我有一个类公司有一个Product对象的集合。 I want to show the following table: 我想显示下表:

替代文字

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). 我仍然没有弄清楚如何使用子表(在所有示例中,我发现subTable与主表具有完全相同的列)。 Presumably, I need to play with rowspans in the first two columns, but I still have not found the way. 据推测,我需要在前两列中使用rowpans,但我仍然没有找到方法。

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 : 更新1:我尝试将左侧列的行间距设置为列表或产品的大小,然后:

  • 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)} 我通过将其呈现的属性设置为#{myFuncs:sizeOf(company.products)}来有条件地执行此操作
  • If the products are >= 1 then I iterate over them with 如果产品> = 1,那么我用它迭代它们 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. 在该循环中,我插入两列(一个用于产品名称,一个用于描述),对于除第一个产品名称列以外的每个产品名称列,我将breakBefore属性设置为#{!myFunc:firstProduct(company.products,product)} ,对于除第一个产品名称之外的所有产品名称,其评估结果为true。

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. 不幸的是,这对我不起作用,因为a4j:repeat中的列根本没有出现 - 不是因为渲染的标记。 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> . 更新2:该问题可能与本文有关 ,表明迭代组件(例如<a4j:repeat>)和标记<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. 第一个在渲染时发生,而第二个在渲染时运行,当JSF组件放在页面的组件树上时。

I tried to get the rich:columns outside the a4j:repeat and they get rendered (of course, not as expected, but they do). 我试图获得富人:a4j之外的列:重复并且它们被渲染(当然,不像预期的那样,但它们确实如此)。

You can do this without those complex forEachs. 你可以在没有复杂的forEachs的情况下做到这一点。 You just need to take advantage of subTable and the rowKeyVar. 您只需要利用subTable和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. 请注意,我正在使用具有Jboss Extended EL的Seam,它允许我在集合上调用size()。 If you aren't using this you can use that prs:collectionSize() or fn:length() as a substitute. 如果您不使用它,则可以使用prs:collectionSize()或fn:length()作为替代。

This also works nicely with the Richfaces datascroller. 这也适用于Richfaces datascroller。

Hope this helps. 希望这可以帮助。

D. D.

There's unfortunately no rowspan support in JSF UIData components. 遗憾的是,JSF UIData组件中没有UIData支持。 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 eg <br/> after each item). 你可以使用另一个UIData组件迭代它,例如h:dataTable (渲染<table> ), t:dataList (渲染<ul> )或a4j:repeat (不渲染任何东西,你需要在每个项目之后使用例如<br/> )。

Semi-pseudo based on the basic JSF components: 基于JSF基本组件的半伪:

<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. 以聪明的方式使用CSS,使其看起来像rowpans。

OK, based on the last update, created the page doing the iterations using c:forEach (while building the component tree). 好的,基于上次更新,使用c:forEach (构建组件树时)创建了执行迭代的页面。 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). 这需要花费太多时间(大约20家公司和200种产品需要大约3秒100%的CPU)。 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. 我怀疑这是因为for c:forEach循环基本上构建了一个巨大的组件树,它必须被渲染,而不是组件树更小的初始方法。
  • 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内部的迭代基本上被忽略):

<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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM