This example shows a simple master-detail table implemented using rich:dataTable and rich:collapsibleSubTable components.
<!DOCTYPE html> <ui:composition xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core" xmlns:ui="http://java.sun.com/jsf/facelets" xmlns:a4j="http://richfaces.org/a4j" xmlns:rich="http://richfaces.org/rich"> <rich:dataTable var="record" value="#{reportBean.expReport.records}"> <f:facet name="header"> <rich:columnGroup> <rich:column rowspan="2"> </rich:column> <rich:column colspan="3"> <h:outputText value="Expenses" /> </rich:column> <rich:column rowspan="2"> <h:outputText value="subtotals" /> </rich:column> <rich:column breakRowBefore="true"> <h:outputText value="Meals" /> </rich:column> <rich:column> <h:outputText value="Hotels" /> </rich:column> <rich:column> <h:outputText value="Transport" /> </rich:column> </rich:columnGroup> </f:facet> <rich:column colspan="5"> <h:outputText value="#{record.city}" /> </rich:column> <rich:collapsibleSubTable var="expense" value="#{record.items}"> <rich:column> <h:outputText value="#{expense.day}" /> <f:facet name="footer"> <div /> </f:facet> </rich:column> <rich:column> <h:outputText value="#{expense.meals}"> <f:convertNumber pattern="$####.00" /> </h:outputText> <f:facet name="footer"> <h:outputText value="#{record.totalMeals}"> <f:convertNumber pattern="$####.00" /> </h:outputText> </f:facet> </rich:column> <rich:column> <h:outputText value="#{expense.hotels}"> <f:convertNumber pattern="$####.00" /> </h:outputText> <f:facet name="footer"> <h:outputText value="#{record.totalHotels}"> <f:convertNumber pattern="$####.00" /> </h:outputText> </f:facet> </rich:column> <rich:column> <h:outputText value="#{expense.transport}"> <f:convertNumber pattern="$####.00" /> </h:outputText> <f:facet name="footer"> <h:outputText value="#{record.totalTransport}"> <f:convertNumber pattern="$####.00" /> </h:outputText> </f:facet> </rich:column> <rich:column> <f:facet name="footer"> <h:outputText value="#{record.total}"> <f:convertNumber pattern="$####.00" /> </h:outputText> </f:facet> </rich:column> </rich:collapsibleSubTable> <f:facet name="footer"> <rich:columnGroup> <rich:column>Totals</rich:column> <rich:column> <h:outputText value="#{reportBean.expReport.totalMeals}"> <f:convertNumber pattern="$####.00" /> </h:outputText> </rich:column> <rich:column> <h:outputText value="#{reportBean.expReport.totalHotels}"> <f:convertNumber pattern="$####.00" /> </h:outputText> </rich:column> <rich:column> <h:outputText value="#{reportBean.expReport.totalTransport}"> <f:convertNumber pattern="$####.00" /> </h:outputText> </rich:column> <rich:column> <h:outputText value="#{reportBean.expReport.grandTotal}"> <f:convertNumber pattern="$####.00" /> </h:outputText> </rich:column> </rich:columnGroup> </f:facet> </rich:dataTable> </ui:composition>
package org.richfaces.demo.tables; import javax.faces.bean.ManagedBean; import javax.faces.bean.RequestScoped; import org.richfaces.demo.tables.model.expenses.ExpenseReport; @ManagedBean @RequestScoped public class ReportBean { ExpenseReport expReport; public ExpenseReport getExpReport() { if (expReport == null) { expReport = new ExpenseReport(); } return expReport; } public void setExpReport(ExpenseReport expReport) { this.expReport = expReport; } }
package org.richfaces.demo.tables.model.expenses; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ExpenseReport { private List<ExpenseReportRecord> records = null; public List<ExpenseReportRecord> getRecords() { if (records == null) { initRecords(); } return records; } public void setRecords(List<ExpenseReportRecord> records) { this.records = records; } public double getTotalMeals() { double ret = 0.0; Iterator<ExpenseReportRecord> it = getRecords().iterator(); while (it.hasNext()) { ExpenseReportRecord record = (ExpenseReportRecord) it.next(); ret += record.getTotalMeals(); } return ret; } public double getTotalHotels() { double ret = 0.0; Iterator<ExpenseReportRecord> it = getRecords().iterator(); while (it.hasNext()) { ExpenseReportRecord record = (ExpenseReportRecord) it.next(); ret += record.getTotalHotels(); } return ret; } public double getTotalTransport() { double ret = 0.0; Iterator<ExpenseReportRecord> it = getRecords().iterator(); while (it.hasNext()) { ExpenseReportRecord record = (ExpenseReportRecord) it.next(); ret += record.getTotalTransport(); } return ret; } public double getGrandTotal() { return getTotalMeals() + getTotalHotels() + getTotalTransport(); } public int getRecordsCount() { return getRecords().size(); } private void initRecords() { records = new ArrayList<ExpenseReportRecord>(); ExpenseReportRecord rec; rec = new ExpenseReportRecord(); rec.setCity("San Jose"); rec.getItems().add(new ExpenseReportRecordItem("25-Aug-97", 37.74, 112.0, 45.0, "San Jose")); rec.getItems().add(new ExpenseReportRecordItem("26-Aug-97", 27.28, 112.0, 45.0, "San Jose")); records.add(rec); rec = new ExpenseReportRecord(); rec.setCity("Seattle"); rec.getItems().add(new ExpenseReportRecordItem("27-Aug-97", 96.25, 109.0, 36.00, "Seattle")); rec.getItems().add(new ExpenseReportRecordItem("28-Aug-97", 35.0, 109.0, 36.0, "Seattle")); records.add(rec); } }
package org.richfaces.demo.tables.model.expenses; import java.util.ArrayList; import java.util.Iterator; import java.util.List; public class ExpenseReportRecord { private String city; private List<ExpenseReportRecordItem> items = new ArrayList<ExpenseReportRecordItem>(); public String getCity() { return city; } public void setCity(String city) { this.city = city; } public List<ExpenseReportRecordItem> getItems() { return this.items; } public void setItems(List<ExpenseReportRecordItem> items) { this.items = items; } public double getTotalMeals() { double ret = 0.0; Iterator<ExpenseReportRecordItem> it = items.iterator(); while (it.hasNext()) { ExpenseReportRecordItem item = (ExpenseReportRecordItem) it.next(); ret += item.getMeals(); } return ret; } public double getTotalHotels() { double ret = 0.0; Iterator<ExpenseReportRecordItem> it = items.iterator(); while (it.hasNext()) { ExpenseReportRecordItem item = (ExpenseReportRecordItem) it.next(); ret += item.getHotels(); } return ret; } public double getTotalTransport() { double ret = 0.0; Iterator<ExpenseReportRecordItem> it = items.iterator(); while (it.hasNext()) { ExpenseReportRecordItem item = (ExpenseReportRecordItem) it.next(); ret += item.getTransport(); } return ret; } public double getTotal() { return getTotalMeals() + getTotalHotels() + getTotalTransport(); } public int getItemsCount() { return getItems().size(); } }
package org.richfaces.demo.tables.model.expenses; public class ExpenseReportRecordItem { private String city; private String day; private double meals; private double hotels; private double transport; public ExpenseReportRecordItem(String day, double meals, double hotels, double transport, String city) { this.city = city; this.day = day; this.meals = meals; this.hotels = hotels; this.transport = transport; } public String getCity() { return city; } public void setCity(String city) { this.city = city; } public String getDay() { return day; } public void setDay(String day) { this.day = day; } public double getHotels() { return hotels; } public void setHotels(double hotels) { this.hotels = hotels; } public double getMeals() { return meals; } public void setMeals(double meals) { this.meals = meals; } public double getTransport() { return transport; } public void setTransport(double transport) { this.transport = transport; } public double getTotal() { return meals + hotels + transport; } }