2010-01-08 5 views
9

Je dois créer un riche: dataTable (ou même étendu) avec les caractéristiques suivantes:riche: datatable question rowspan

J'ai une société de classe ayant une collection d'objets de produit. Je veux montrer le tableau suivant:

alt text

Je n'ai toujours pas compris comment faire cela avec un sous-table (dans tous les exemples que je trouve la sous-table a les mêmes colonnes exactes que la table principale). Vraisemblablement, je dois jouer avec les rangées dans les deux premières colonnes, mais je n'ai toujours pas trouvé le chemin.

Quelqu'un pourrait-il fournir un pseudo-code pour cela?

À la votre!

MISE À JOUR 1: J'ai essayé mis le rowspan des colonnes dans la gauche comme la taille de la liste ou de produits, puis:

  • si les produits est vide (pas de produits pour l'entreprise encore), j'imprime deux colonnes. Je le fais conditionnellement en réglant leur rendu attribut à # {myFuncs: sizeof (company.products)}
  • Si les produits sont sur eux> = 1 alors j'itérer avec et à l'intérieur de cette boucle insérer deux colonnes (une pour le nom de produit et une pour la description), et pour chaque colonne de nom de produit sauf la première, j'ai défini l'attribut breakBefore sur # {! myFunc: firstProduct (company.products, product)}, qui évalue à vrai pour tous les noms de produits sauf le premier.

Malheureusement, cela ne fonctionne pas pour moi, parce que les colonnes à l'intérieur du a4j: répéter ne semblent pas du tout - pas à cause de la tag rendu. La boucle est correcte car si j'imprime du texte standard, elle apparaît.

Existe-t-il un moyen de réaliser des rangées ou est-ce que je me casse la tête sur le mur?

MISE À JOUR 2: La question est probablement liée à ce article, en indiquant les différences entre les composants d'itération tels que < a4j: répéter> et la balise < c: forEach>. La première a lieu au moment du rendu, tandis que la seconde fonctionne plus tôt, lorsque les composants JSF sont placés dans l'arborescence des composants de la page.

J'ai essayé d'obtenir les riches: colonnes en dehors de l'a4j: répétition et ils sont rendus (bien sûr, pas comme prévu, mais ils le font).

Répondre

6

Vous pouvez faire ceci sans ces complexes pourEachs. Vous avez juste besoin de tirer parti de subTable et de rowKeyVar.

Par exemple:

<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 parfaitement pour moi. Notez que j'utilise Seam qui a Jboss Extended EL qui me permet d'appeler size() sur la collection. Si vous n'utilisez pas cela, vous pouvez utiliser prs: collectionSize() ou fn: length() comme substitut.

Cela fonctionne également très bien avec le crypteur de données Richfaces.

Espérons que cela aide.

D.

+0

J'essaie cela. ** Mais ** cela montre seulement les entreprises qui ont ** des ** produits.Il y a des entreprises qui n'ont pas de produits, que j'aimerais voir apparaître (les colonnes de produits restantes devraient être vides). Existe-t-il un support pour cela? –

+1

Ne pas utiliser cette approche. C'est la limitation. Vous pouvez toutefois truquer les lignes en post-traitant les sociétés et en ajoutant un produit vide là où il n'en existe pas. – Damo

+1

J'ai poursuivi la discussion sur la communauté Richfaces: http://community.jboss.org/message/541744. Là, nous avons trouvé une solution de contournement même pour les entreprises avec des produits ** non **. –

2

Il n'y a malheureusement pas de support rowspan dans les composants JSF UIData. Le mieux ce que vous pouvez faire est de simplement afficher la collection de produits dans le même ligne.Vous pouvez itérer dessus à l'aide d'un autre composant UIData tel que h:dataTable (<table> rend), t:dataList (<ul> rend) ou a4j:repeat (rend rien, vous devez utiliser par exemple <br/> après chaque élément).

semi-pseudo basée sur les composants JSF de base:

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

Utilisez CSS la façon intelligente de sorte qu'il ressemble à rowspans.

+0

Merci l'homme. Je pense que je pourrais peut-être utiliser le riche: extendedDataTable pour ce que je dois faire. Il a une fonctionnalité qu'ils appellent "Group Rows by Column", mais l'inconvénient est que je ne peux que grouper par une colonne. Pensez-vous qu'une autre bibliothèque de composants (par exemple, Icefaces) a une base de données qui fait ce dont j'ai besoin? À votre santé! –

+1

Désolé, je ne peux pas en dire beaucoup à ce sujet. J'ai seulement une expérience pratique avec Mojarra et Tomahawk et juste un peu avec RichFaces/Ajax4jsf. – BalusC

+0

En outre, RichFaces datatable _does_ possède un attribut rowspan pour les colonnes. Je n'ai pas trouvé le moyen de l'utiliser pour faire la chose spécifique que je veux faire. –

0

OK, basé sur la dernière mise à jour, a créé la page en effectuant les itérations en utilisant c: forEach (lors de la construction de l'arborescence des composants). La solution que je fournis fonctionne, mais quelque chose se sent mal à ce sujet parce que:

  • Cela prend trop de temps (~ 3 secondes 100% CPU pour environ 20 entreprises et 200 produits). Je suppose que c'est parce que la boucle for c: forEach construit essentiellement un arbre de composants énorme, qui doit être rendu, au lieu des approches initiales où l'arbre des composants était beaucoup plus petit.
  • Je pense que je devrai reconstruire l'ensemble de l'arborescence des composants pour chaque changement de données, au lieu de simplement le rendre à nouveau.

Quoi qu'il en soit, au code. Ce que je faisais quelque chose comme ça (n'ont pas testé celui ci-dessous, mais vous aurez l'image Notez que l'itération dans les riches. DataTable est essentiellement ignoré):

<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

Vous pouvez également faire simplement la base '' # {not bean.collection} 'et JSTL' # {fn: longueur (bean .collection)} 'à la place de' prs: collectionSize'. – BalusC