ZK Charts Drill Down Example

Note: You need ZK EE License for this.

Video Demo


Maven

	<dependency>
<groupId>org.zkoss.chart</groupId>
<artifactId>zkcharts</artifactId>
<version>2.0.0</version>
</dependency>

The following code  is from my project. You can check  the code for details.



<?taglib uri="http://www.zkoss.org/dsp/web/core" prefix="c"?>
<zk>
<window id="chartReceiptdaily" height="100%"
contentStyle="overflow:auto;"
viewModel="@id('vm') @init('com.product.webapp.charts.ChartReceiptDailyVM')"
apply="org.zkoss.bind.BindComposer">
<panel id="panel" title="Filter" framable="true" border="normal"
collapsible="true" open="true">
<panelchildren>
<separator />
<vgrid>
<columns>
<column hflex="min"></column>
<column hflex="min"></column>
<column hflex="min"></column>
<column hflex="1"></column>
<column hflex="1"></column>
</columns>
<rows>
<row>
<hbox hflex="1">
<vlayout>
<flabel value="Month" />
<EnumDrpDown labelFormat="2"
showDesc="false" hflex="1" dropDownType="1" id="monthnames"
EnumType="monthnames" name="monthnames"
value="@bind(vm.billingCond.monthName)" />
</vlayout>
</hbox>
<vlayout>
<hbox>
<vlayout>
<flabel value="Year" />
<intbox format="####"
value="@bind(vm.billingCond.year)" maxlength="4"
placeholder="YYYY" />
</vlayout>
</hbox>
</vlayout>
<vlayout>
<flabel value="Location" />
<hbox>
<ftextbox hflex="1"
sclass="highlightText" ctrlKeys="#del"
onCtrlKey="@command('onClearLookupValues',type='location')"
onFocus="@command('onFocusLookupValues',target=self)"
onDoubleClick="@command('jumpToScreen',code=self.value,screenNum=101)"
value="@bind(vm.billingCond.locationCode)" name="location" />
<toolbarbutton
sclass="gridToolbarButton" image="/images/smallsearch.png"
onClick="@command('OnLookUp',type='location')" />
</hbox>
</vlayout>
<vlayout>
<dlabel></dlabel>
<fbutton label="Apply" id="search"
onClick="@command('onApplyCondition',action=1)">
</fbutton>
</vlayout>
</row>
</rows>
</vgrid>
<separator />
</panelchildren>
</panel>
<div visible="@bind(not vm.showTitle)">
<separator></separator>
<separator></separator>
<separator></separator>
</div>


<div id="divchart"></div>
<separator></separator>
<div align="center">
<flabel sclass="screenheaderlabel"
visible="@bind(not vm.showingDetail)"
value="Click on the Totals to view Summary by Receipt Payment Mode." />
<fbutton label="Go Back" visible="@bind(vm.showingDetail)"
onClick="@command('goBack')">
</fbutton>
<separator></separator>
</div>

<separator></separator>
<separator></separator>

<panel width="65%">
<panelchildren>
<separator></separator>
<listbox id="" mold="paging" sclass="mylist"
height="400px" selectedItem="@bind(vm.selectedData)"
model="@load(vm.dataList)">
<listhead sizable="true">
<listheader label="@bind(vm.colCaption)"
hflex="1" sort="auto(data)" />
<listheader label="Receipts" hflex="1"
sort="auto(count)" />
<listheader label="Billed Amount" hflex="1"
sort="auto(amount)" align="right" />
</listhead>
<template name="model" var="p1">
<listitem>
<listcell label="@load(p1.data)" />
<listcell label="@load(p1.count)" />
<listcell
label="@load(c:formatNumber(p1.amount, '#,###.00'))" />
</listitem>
</template>
<listfoot>
<listfooter>
<label value="Grand Total" />
</listfooter>

<listfooter>
<label value="@bind(vm.totalCount)" />
</listfooter>
<listfooter>
<label
value="@bind(c:formatNumber(vm.totalAmount, '#,###.00'))" />
</listfooter>
</listfoot>
</listbox>
</panelchildren>
</panel>
<separator></separator>
<separator></separator>
</window>
</zk>



ViewModel

package com.product.webapp.charts;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Iterator;
import java.util.List;

import org.zkoss.bind.BindUtils;
import org.zkoss.bind.annotation.AfterCompose;
import org.zkoss.bind.annotation.BindingParam;
import org.zkoss.bind.annotation.Command;
import org.zkoss.bind.annotation.ContextParam;
import org.zkoss.bind.annotation.ContextType;
import org.zkoss.bind.annotation.ExecutionArgParam;
import org.zkoss.chart.Chart;
import org.zkoss.chart.Charts;
import org.zkoss.chart.ChartsEvent;
import org.zkoss.chart.Tooltip;
import org.zkoss.chart.plotOptions.PiePlotOptions;
import org.zkoss.zk.ui.Component;
import org.zkoss.zk.ui.event.Event;
import org.zkoss.zk.ui.select.Selectors;
import org.zkoss.zk.ui.select.annotation.Wire;
import org.zkoss.zk.ui.util.Clients;
import org.zkoss.zul.CategoryModel;
import org.zkoss.zul.SimpleCategoryModel;
import org.zkoss.zul.SimpleSingleValueCategoryModel;
import org.zkoss.zul.Window;

@SuppressWarnings("unchecked")
public class ChartReceiptDailyVM extends BaseChartVM {

@Wire("#chartReceiptdaily")
private Window win;
private CategoryModel model;
private String theme;
private boolean showingDetail = false;
private String colCaption = "";

public String getColCaption() {
return colCaption;
}

public void setColCaption(String colCaption) {
this.colCaption = colCaption;
}

public boolean isShowingDetail() {
return showingDetail;
}

public void setShowingDetail(boolean showingDetail) {
this.showingDetail = showingDetail;
}

@AfterCompose
public void initSetup(@ContextParam(ContextType.VIEW) Component view,
@ExecutionArgParam("theme") String theme) {
Selectors.wireComponents(view, this, false);
super.initSetup(win);
this.theme = theme;
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
String[] monthName = { "January", "February", "March", "April", "May",
"June", "July", "August", "September", "October", "November",
"December" };
String month = monthName[now.get(Calendar.MONTH)];
billingCond.setYear(year);
billingCond.setMonthName(month);
onApplyCondition(0);
}

@Command
public void goBack() {
onApplyCondition(0);
}

@SuppressWarnings("rawtypes")
@Command
public void onApplyCondition(@BindingParam("action") Integer action) {
if (action == 1)
this.showTitle = false;
billingCond.setChargeSummaryType("ReceiptDaily");
billingCond.setDay(null);
showingDetail = false;
colCaption = "Day";
divchart.getChildren().clear();
chart = new Charts();
chart.setType("column");
chart.setParent(divchart);
chart.setTitle("Patient Receipts Daily Summary");
chart.setSubtitle("Click on the Totals to view Summary by Receipt Payment Mode");
chart.addEventListener("onPlotClick", new onPlotSelect());
List<Object> results = billingReportService
.getPatientReceiptSummary(billingCond);
if (results.size() == 0)
Clients.showNotification("No Data found for the given condition.",
Clients.NOTIFICATION_TYPE_INFO, null, "middle_center", 1100);

dataList = new ArrayList<ChartDataList>();
this.totalAmount = BigDecimal.ZERO;
model = new SimpleCategoryModel();
Integer week = 0;
BigDecimal amount = BigDecimal.ZERO;
Long noOfReceipts = (long) 0;
String data = "";
for (Iterator it = results.iterator(); it.hasNext();) {
Object[] row = (Object[]) it.next();
week = (Integer) row[0];
amount = (BigDecimal) row[1];
noOfReceipts = (Long) row[2];
data = "Day-" + week;
dataList.add(new ChartDataList(data, noOfReceipts, amount, null));
model.setValue("Practice", week, amount);
totalAmount = totalAmount.add(amount);
totalCount = totalCount + noOfReceipts;
}
chart.getXAxis().setMin(0);
chart.getXAxis().getTitle().setText("Day");

chart.getYAxis().setMin(0);
chart.getYAxis().getTitle().setText("Receipt Amount ");

Tooltip tooltip = chart.getTooltip();
tooltip.setHeaderFormat("<span style=\"font-size:10px\">{point.key}</span><table>");
tooltip.setPointFormat("<tr><td style=\"color:{series.color};padding:0\">{series.name}: </td>"
+ "<td style=\"padding:0\"><b> $ {point.y:.1f} </b></td></tr>");
tooltip.setFooterFormat("</table>");
tooltip.setShared(true);
tooltip.setUseHTML(true);
chart.getPlotOptions().getColumn().setPointPadding(0.2);
chart.getPlotOptions().getColumn().setBorderWidth(0);
chart.getLegend().setEnabled(false);
chart.setModel(model);
super.onSelectChartTheme(this.theme);
BindUtils.postNotifyChange(null, null, this, "*");
}

@SuppressWarnings("rawtypes")
class onPlotSelect implements org.zkoss.zk.ui.event.EventListener {
@Override
public void onEvent(Event event) throws Exception {
showPaymentDetails((Integer) ((ChartsEvent) event).getCategory());
}
}

@SuppressWarnings("rawtypes")
private void showPaymentDetails(Integer day) {
SimpleSingleValueCategoryModel model;
billingCond.setChargeSummaryType("paymentMode");
billingCond.setDay(day);
colCaption = "Mode";
showingDetail = true;
divchart.getChildren().clear();
chart = new Charts();
chart.setType("pie");
chart.setParent(divchart);
chart.setTitle("Receipt By Payment Mode");
List<Object> results = billingReportService
.getPatientReceiptSummary(billingCond);
dataList = new ArrayList<ChartDataList>();
this.totalAmount = BigDecimal.ZERO;
this.totalCount = 0L;
model = new SimpleSingleValueCategoryModel();
for (Iterator it = results.iterator(); it.hasNext();) {
Object[] row = (Object[]) it.next();
dataList.add(new ChartDataList((String) row[0], (Long) row[1],
(BigDecimal) row[2], (String) row[0]));
model.setValue((Comparable<?>) row[0], (Number) row[2]);
totalAmount = totalAmount.add((BigDecimal) row[2]);
totalCount = totalCount + (Long) row[1];
}
chart.setModel(model);
Chart chartOptional = chart.getChart();
chartOptional.setPlotBorderWidth(0);
chartOptional.setBackgroundColor("");
chart.getTooltip().setPointFormat(
"{series.name}: <b>{point.percentage:.1f}%</b>");
PiePlotOptions plotOptions = chart.getPlotOptions().getPie();
plotOptions.setAllowPointSelect(true);
plotOptions.setCursor("pointer");
plotOptions.getDataLabels().setEnabled(true);
plotOptions.setShowInLegend(true);
super.onSelectChartTheme(this.theme);
BindUtils.postNotifyChange(null, null, this, "*");
}
}


Java class to store the results



package com.product.webapp.charts;

import java.math.BigDecimal;

public class ChartDataList {

private String data;
private Long count;
private BigDecimal amount;
private String monthName;

public String getMonthName() {
return monthName;
}

public void setMonthName(String monthName) {
this.monthName = monthName;
}

public ChartDataList(String data, Long count, BigDecimal amount) {
this.data = data;
this.count = count;
this.amount = amount;
}

public ChartDataList(String data, Long count, BigDecimal amount,
String monthName) {
this.data = data;
this.count = count;
this.amount = amount;
this.monthName = monthName;
}

public String getData() {
return data;
}

public void setData(String data) {
this.data = data;
}

public Long getCount() {
return count;
}

public void setCount(Long count) {
this.count = count;
}

public BigDecimal getAmount() {
return amount;
}

public void setAmount(BigDecimal amount) {
this.amount = amount;
}

}