Stephan
Stephan

Reputation: 43083

How to represent nested data in a Primefaces datatable?

Here is my model :

User.java

public class User {
   //...

   public List<User> getFriends() {
      // ...
   }
}

I would like to build a table of user friends like this :

users.jsf

+----------+------------+
|   USER   |   FRIENDS  |
+----------+------------+
|          |    ALICE   |
|          +------------+        
|   ADAM   |    BOB     |
|          +------------+
|          |    PITT    |
+----------+------------+
|          |            |
....

Since there are many users, it's not possible to dump the user table in one go.

The datatable component is ideal in this case because it has built-in pagination support. It is ideal too because it's possible to sort columns...

Unfortunately, I wasn't able to find through the Primefaces examples a way for changing the rowspan in user columns.

How can I build this datatable ?

Some other OP having this similar issue:

EDIT
Here is the final solution I came up with.

Upvotes: 8

Views: 39173

Answers (5)

bilelovitch
bilelovitch

Reputation: 2175

For me there is two solution :

1- If i want to browse user by user and retrieve the list of friends, in this case i prefer the dataList.

<p:dataTable value="#{users.list}" var="u">

    <p:column headerText="USER">#{u.name}</p:column>    
    <p:column headerText="FRIENDS">
        <p:dataList value="#{u.friends}" var="f">
            #{f.name}
        </p:dataTable>
    </p:column>

</p:dataTable>

2- In a case where i can handle directly the list of friends (listFreinds [userName, friend]) or when i'm using JPQL query :

<p:dataTable value="#{users.listFreinds}" var="u" sortBy="#{u.userName}">

    <p:column headerText="USER" groupRow="true">#{u.userName}</p:column>    
    <p:column headerText="FRIENDS">#{u.friend}</p:column>

</p:dataTable>

The second case, is a new native solution with Primefaces Row Grouping since v6.0.11

https://www.primefaces.org/showcase/ui/data/datatable/rowGroup.xhtml

Upvotes: 2

Stephan
Stephan

Reputation: 43083

Based on @Kerem's answer, here is the solution I came up with:

In order to make the nested datable like own rows of main datatable, I have overriden the CSS class .ui-dt-c. Check in h:head the style tag for details.

<?xml version="1.0" encoding="UTF-8"?>
<html
    xmlns="http://www.w3c.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:p="http://primefaces.org/ui"
    xmlns:fn="http://java.sun.com/jsp/jstl/functions"
    xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
    <title>USERS and their friends</title>
    <style>
       .ui-dt-c {
          padding: 0px !important;
       }
    </style>
</h:head>
<h:body>
<h:form id="form">
<p:dataTable
    value="#{users.list}"
    var="u">

    <p:columnGroup type="header">
        <p:row>
            <p:column headerText="USER" />
            <p:column headerText="FRIENDS" />
        </p:row>
    </p:columnGroup>

    <p:column>#{u.name}</p:column>
    <p:column>
        <p:dataTable
            value="#{u.friends}"
            var="f">
            <p:column>#{f.name}</p:column>
        </p:dataTable>
    </p:column>
</p:dataTable>
</h:form>

Upvotes: 2

Catfish
Catfish

Reputation: 19324

Another option is to use ui:repeat inside a column to get all the values of a collection.

Example:

<p:dataTable var="user" value="#{userGroupBacking.users}" id="userTable">

    <p:column headerText="User">
        <h:outputText value="#{user.name}" />
    </p:column>

    <p:column headerText="Groups">
        <ui:repeat var="group" value="#{user.groups}">
            <h:outputText value="#{group.name}" /><br />
        </ui:repeat>
...

Upvotes: 3

Kerem Baydoğan
Kerem Baydoğan

Reputation: 10720

Just use another data table inside your column :)

<h:column>
    <h:dataTable var="friend" value="#{user.friends}">
        <h:column>
            <h:outputText value="#{friend.name}"/>
        </h:column>
    </h:dataTable>
</h:column>

This is how it looks on my localhost

enter image description here

Upvotes: 14

kolossus
kolossus

Reputation: 20691

Primefaces expandable rows should address your need, only you'll need to get creative with the child row component. You could use prime faces data list component as the child row component. It'll look something like:

   <p:row expansion>
    <p:datalist value ="#{yourTableRowVar.friendslist} Var="friend">
    #{friend.firstName}
    </p:datalist>
   </p:row expansion>

Upvotes: 2

Related Questions