2010-01-08 74 views
9

我需要创建一个丰富:dataTable的(甚至扩展),具有以下特点:富:数据表行跨度问题

我有产品对象的集合类公司。我想如下表显示:

alt text

我还没有想出如何与子表(在所有的例子,我发现子表具有完全相同的列作为主表)做到这一点。据推测,我需要在前两栏中使用rowspans,但我仍然没有找到方法。

有人可以为此提供一个伪代码吗?

干杯!

更新1: 我尝试设置列行跨度在左边的列表或产品的大小,然后:

  • 的产品是否为空(无产品该公司呢),我打印了两栏。我这样做是有条件通过其呈现属性设置为#{myFuncs:整型尺寸(company.products)}
  • 如果这些产品是> = 1,那么我遍历他们和循环中我插入两个列(一个用于产品名称和一个用于说明),除了第一个产品名称列以外,我还设置了breakBefore属性到#{!myFunc:firstProduct(company.products,product)},其计算结果为对于除第一个产品名称以外的所有产品名称均为真

不幸的是,这并没有为我工作,因为A4J内部中的列:重复不会出现在所有 - 不是因为呈现标签。循环是正确的,因为如果我打印其他标准文本,它就会出现。

有没有办法实现rowspan,还是我把我的头撞在墙上?

更新2: 问题可能与此article,说明如< A4J迭代组件之间的差别:重复>和标签< C:的forEach>。第一个是在渲染时发生,而第二个是在JSF组件放置到页面的组件树上时运行的。

我试图让rich:a4j:repeat之外的列被渲染(当然,并不像预期的那样,但是它们是这样做的)。

回答

6

你可以做这没有那些复杂的forEachs。你只需要利用subTable和rowKeyVar。

例如:

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

完美呈现给我。请注意,我正在使用带有Jboss Extended EL的Seam,它允许我调用集合上的size()。如果你不使用它,你可以使用prs:collectionSize()或fn:length()作为替代。

这也适用于Richfaces datascroller。

希望这会有所帮助。

D.

+0

我正在尝试。 **但是**它只显示**有**产品的公司。有些公司没有我想要出现的产品(其余产品列应该是空的)。 有支持吗? – 2010-04-20 16:44:31

+1

不使用这种方法。这是限制。但是,您可以通过对公司进行后处理并添加空白产品来伪造行。 – Damo 2010-04-20 22:33:22

+1

我继续讨论Richfaces社区:http://community.jboss.org/message/541744。在那里,我们发现了一个解决方法,即使是** no **产品的公司也是如此。 – 2010-06-09 08:31:35

2

不幸的是,在JSF UIData组件中没有行支持。最好你能做的只是在相同的行中显示产品集合。您可以使用另一个UIData组件迭代它如h:dataTable(渲染<table>),t:dataList(渲染<ul>)或a4j:repeat(渲染什么,你需要在每个项目后如<br/>使用)。基于基本的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> 

使用CSS聪明的办法,使其看起来像rowspans。

+0

谢谢你。我想也许我可以使用rich:extendedDataTable来完成我需要做的事情。它有一个名为“按行列组”的功能,但缺点是我只能按一列分组。你认为另一个组件库(即Icefaces)有一个可以满足我需要的数据表吗?干杯! – 2010-01-09 18:49:41

+1

对不起,不能多说。我对Mojarra和Tomahawk只有很强的经验,并且只需要一点点RichFaces/Ajax4jsf。 – BalusC 2010-01-09 18:55:21

+0

此外,RichFaces数据表_does_具有列的rowspan属性。我还没有找到用它来做我想做的具体事情的方式。 – 2010-01-13 09:05:38

0

好的,根据上次更新,使用c:forEach(构建组件树时)创建了执行迭代的页面。该解决方案我提供的作品,但有什么感觉错了,因为:

  • 它需要太多的时间(〜3秒100%的CPU约20家公司和200级的产品)。我怀疑这是因为for c:forEach循环基本上构建了一个巨大的组件树,它必须被渲染,而不是组件树更小的初始方法。
  • 我想我将不得不为数据中的每个更改重新构建整个组件树,而不是仅仅重新呈现它。

无论如何,代码。我所做的是像这样(没有测试下面的一个,但你会得到的图片请注意,丰富的内部迭代:数据表上基本上是忽略不计):

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

+2

你也可以做基本的EL'#{not empty bean.collection}'和JSTL的'#{fn:length(bean .collection)}'而不是'prs:collectionSize'。 – BalusC 2010-01-15 12:01:57