Rows can be grouped in two ways, using rowGroup component or with groupRow attribute on a column.
<div class="card">
<h5 class="first">Header Row</h5>
<h:form>
<p:dataTable var="customer" value="#{dtRowGroupView.customers}" sortBy="#{customer.representative.name}">
<p:headerRow field="representative.name"
expandable="true"
expanded="#{customer.representative.name != 'Stephen Shaw'}">
<p:column colspan="6">
<div class="inline-flex align-items-center" style="vertical-align: middle">
<p:graphicImage name="images/avatar/#{customer.representative.image}" library="demo" width="32" style="vertical-align: middle"/>
<h:outputText styleClass="ml-2" value="#{customer.representative.name}"/>
</div>
</p:column>
</p:headerRow>
<p:column headerText="Representative">
<h:outputText value="#{customer.representative.name}" />
</p:column>
<p:column headerText="Name">
<h:outputText value="#{customer.name}" />
</p:column>
<p:column headerText="Country">
<span class="flag flag-#{customer.country.code}" style="width: 30px; height: 20px"/>
<h:outputText style="vertical-align: middle; margin-left: .5rem" value="#{customer.country}"/>
</p:column>
<p:column headerText="Company">
<h:outputText value="#{customer.company}" />
</p:column>
<p:column headerText="Status">
<span class="customer-badge status-#{customer.status.name().toLowerCase()}">#{customer.status}</span>
</p:column>
<p:column headerText="Date">
<h:outputText value="#{customer.date}">
<f:convertDateTime pattern="MM/dd/yyyy" type="localDate"/>
</h:outputText>
</p:column>
<p:summaryRow>
<p:column colspan="5" style="text-align:right">
<h:outputText value="Total Customers:"/>
</p:column>
<p:column>
<h:outputText value="#{dtRowGroupView.getTotalCount(customer.representative.name)}"/>
</p:column>
</p:summaryRow>
</p:dataTable>
</h:form>
</div>
<div class="card">
<h5>Rowspan</h5>
<h:form>
<p:dataTable var="customer" value="#{dtRowGroupView.customers}">
<p:column headerText="Representative" groupRow="true">
<p:graphicImage name="images/avatar/#{customer.representative.image}" library="demo"
width="32" style="vertical-align: middle"/>
<h:outputText style="vertical-align: middle; margin-left: .5rem"
value="#{customer.representative.name}"/>
</p:column>
<p:column headerText="Name">
<h:outputText value="#{customer.name}" />
</p:column>
<p:column headerText="Country">
<span class="flag flag-#{customer.country.code}" style="width: 30px; height: 20px"/>
<h:outputText style="vertical-align: middle; margin-left: .5rem" value="#{customer.country}"/>
</p:column>
<p:column headerText="Company">
<h:outputText value="#{customer.company}" />
</p:column>
<p:column headerText="Status">
<span class="customer-badge status-#{customer.status.name().toLowerCase()}">#{customer.status}</span>
</p:column>
<p:column headerText="Date">
<h:outputText value="#{customer.date}">
<f:convertDateTime pattern="MM/dd/yyyy" type="localDate"/>
</h:outputText>
</p:column>
</p:dataTable>
</h:form>
</div>
@Named("dtRowGroupView")
@ViewScoped
public class RowGroupView implements Serializable {
private List<Customer> customers;
@Inject
private CustomerService service;
@PostConstruct
public void init() {
customers = service.getCustomers(50);
}
public long getTotalCount(String name) {
return customers.stream().filter(customer -> name.equals(customer.getRepresentative().getName())).count();
}
public List<Customer> getCustomers() {
return customers;
}
public void setService(CustomerService service) {
this.service = service;
}
}
@Named
@ApplicationScoped
public class CustomerService {
private Random random = new SecureRandom();
private Country[] countries;
private Representative[] representatives;
private String[] firstNames;
private String[] lastNames;
private String[] companies;
@PostConstruct
public void init() {
countries = new Country[]{
new Country(0, "Argentina", "ar"),
new Country(1, "Australia", "au"),
new Country(2, "Brazil", "br"),
new Country(3, "Canada", "ca"),
new Country(4, "Germany", "de"),
new Country(5, "France", "fr"),
new Country(6, "India", "in"),
new Country(7, "Italy", "it"),
new Country(8, "Japan", "jp"),
new Country(9, "Russia", "ru"),
new Country(10, "Spain", "es"),
new Country(11, "United Kingdom", "gb")};
companies = new String[]{"Benton, John B Jr", "Chanay, Jeffrey A Esq", "Chemel, James L Cpa", "Feltz Printing Service",
"Printing Dimensions", "Chapman, Ross E Esq", "Morlong Associates", "Commercial Press", "Truhlar And Truhlar Attys",
"King, Christopher A Esq", "Dorl, James J Esq", "Rangoni Of Florence", "Feiner Bros", "Buckley Miller Wright",
"Rousseaux, Michael Esq"};
representatives = new Representative[]{
new Representative("Amy Elsner", "amyelsner.png"),
new Representative("Anna Fali", "annafali.png"),
new Representative("Asiya Javayant", "asiyajavayant.png"),
new Representative("Bernardo Dominic", "bernardodominic.png"),
new Representative("Elwin Sharvill", "elwinsharvill.png"),
new Representative("Ioni Bowcher", "ionibowcher.png"),
new Representative("Ivan Magalhaes", "ivanmagalhaes.png"),
new Representative("Onyama Limba", "onyamalimba.png"),
new Representative("Stephen Shaw", "stephenshaw.png"),
new Representative("Xuxue Feng", "xuxuefeng.png")};
firstNames = new String[]{"James", "David", "Jeanfrancois", "Ivar", "Tony",
"Adams", "Claire", "Costa", "Juan", "Maria", "Jennifer",
"Stacey", "Leja", "Morrow", "Arvin", "Darci", "Izzy",
"Ricardo", "Clifford", "Emily", "Kadeem", "Mujtaba", "Aika",
"Mayumi", "Misaki", "Silvio", "Nicolas", "Antonio",
"Deepesh", "Aditya", "Aruna", "Jones", "Julie", "Smith",
"Johnson", "Francesco", "Salvatore", "Kaitlin", "Faith",
"Maisha", "Jefferson", "Leon", "Rodrigues", "Alejandro",
"Munro", "Cody", "Chavez", "Sinclair", "Isabel", "Octavia",
"Murillo", "Greenwood", "Wickens", "Ashley"};
lastNames = new String[]{"Butt", "Darakjy", "Venere", "Paprocki", "Foller",
"Morasca", "Tollner", "Dilliard", "Wieser", "Marrier", "Amigon",
"Maclead", "Caldarera", "Ruta", "Albares", "Poquette", "Garufi",
"Gaucho", "Rim", "Whobrey", "Flosi", "Nicka", "Inouye",
"Kolmetz", "Royster", "Slusarski", "Iturbide", "Caudy",
"Chui", "Kusko", "Figeroa", "Vocelka", "Stenseth", "Glick",
"Sergi", "Shinko", "Stockham", "Ostrosky", "Gillian",
"Rulapaugh", "Schemmer", "Oldroyd", "Campain", "Perin",
"Ferencz", "Saylors", "Briddick", "Waycott", "Bowley", "Malet",
"Malet", "Bolognia", "Nestle", "Doe"};
}
public List<Customer> getCustomers(int number) {
List<Customer> customers = new ArrayList<>();
for (int i = 0; i < number; i++) {
customers.add(
new Customer(i + 1000, getName(), getCompany(), getCountry(), getDate(),
CustomerStatus.random(), getActivity(), getRepresentative()));
}
return customers;
}
public List<Country> getCountries() {
return Arrays.asList(countries);
}
public CustomerStatus[] getCustomerStatus() {
return CustomerStatus.values();
}
public List<Representative> getRepresentatives() {
return Arrays.asList(representatives);
}
private String getName() {
return firstNames[random.nextInt(firstNames.length)] + Constants.SPACE
+ (char) (random.nextInt(26) + 'A') + Constants.SPACE
+ lastNames[random.nextInt(lastNames.length)];
}
private Country getCountry() {
return countries[random.nextInt(countries.length)];
}
private String getCompany() {
return companies[random.nextInt(companies.length)];
}
private LocalDate getDate() {
LocalDate now = LocalDate.now();
long randomDay = ThreadLocalRandom.current().nextLong(now.minusDays(30).toEpochDay(), now.toEpochDay());
return LocalDate.ofEpochDay(randomDay);
}
private int getActivity() {
return random.nextInt(100);
}
private Representative getRepresentative() {
return representatives[random.nextInt(representatives.length)];
}
}