## With Safari, you learn the way you learn best. Get unlimited access to videos, live online training, learning paths, books, tutorials, and more.

No credit card required

# 4.2. Creating a Vertical Bar Chart

## Problem

You want to create a data-driven vertical bar chart on a web page without having to use an applet or a graphics library.

## Solution

Use nested HTML tables with the `height` percentages calculated dynamically:

```<table height="500" width="60%">
<tr>
<logic:iterate id="row"
name="foo"
property="bar">
<td valign="bottom">
<table height='<bean:write name="row"
property="percentage"/>%'
width="100%" bgcolor="#003366">
<tr>
<td align="center" valign="top">
<font color="white">
<bean:write name="row"
property="percentage"/>%
</font>
</td>
</tr>
</table>
</td>
</logic:iterate>
</tr>
<tr align="center" height="10%">
<logic:iterate id="row"
name="foo"
property="bar">
<td align="center" width="50">
<bean:write name="row" property="label"/>
</td>
</logic:iterate>
</tr>
</table>```

## Discussion

In Recipe 4.1, the chart is generated using a `logic:iterate` loop. On each pass through the loop, a table row is generated. The first column of the each row holds the label, and the second column contains the bar graph. The graph is generated using a numeric value to specify the width percentage for a nested table that has a different background color.

A vertical bar chart can be thought of as a horizontal bar chart flipped on its side. The table for a horizontal chart has n rows by two columns, in which n is the size of the Collection being iterated over, and the two columns are for the label and the bar. The vertical bar chart, on the other hand, uses n columns by two rows. Instead of each pass through the loop generating a row, each pass generates a column. So, to generate a vertical bar chart, you use two iteration loops. The first loop generates the top row containing the bars. The second loop generates the bottom row containing the labels.

The mechanism for creating the bar is similar to that used for the horizontal bar chart: a table is nested within a table cell. For the vertical chart, the height percentages are set instead of the width.

```<table height='<bean:write name="dayEntry"
property="chancePrecip"/>%'
width="100%" bgcolor="#003366">```

You should locate the text containing the numeric value for each bar at the top end of the graphic. You set the value of the `valign` attribute for the `td` cell to top to get this alignment.

A concrete example helps pull this all together. You can use the same `WeeklyForecast` JavaBean and related classes that are used in Recipe 4.1 (shown in Examples Example 4-1 and Example 4-2). Example 4-5 shows the JSP page (vertical_chart.jsp) that generates the vertical bar chart.

Example 4-5. Vertical bar chart JSP

```<%@ page contentType="text/html;charset=UTF-8" language="java" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean" %>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-logic" prefix="logic" %>
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>

<html>
<title>Struts Cookbook - Chapter 04</title>
<body bgcolor="white">
<h2>Struts Cookbook Chapter 4 Examples</h2>
<div align="center">
<hr />
<h3>Color Bar Chart (vertical)</h3>
<table height="500" width="60%">
<tr>
<logic:iterate id="dayEntry"
name="weeklyWeather"
property="weekForecast">
<td valign="bottom">
<table height='<bean:write name="dayEntry"
property="chancePrecip"/>%'
width="100%" bgcolor="#003366">
<tr>
<td align="center" valign="top">
<font color="white">
<bean:write name="dayEntry"
property="chancePrecip"/>%
</font>
</td>
</tr>
</table>
</td>
</logic:iterate>
</tr>
<tr align="center" height="10%">
<logic:iterate id="dayEntry"
name="weeklyWeather"
property="weekForecast">
<td align="center" width="50">
<bean:write name="dayEntry" property="day"/>
</td>
</logic:iterate>
</tr>
</table>
</div>
</body>
</html>```

The rendered chart is shown in Figure 4-3.

If you look closely, you'll notice that the width of the bars is inconsistent. That's because the width of the label (day of week) displayed on the bottom row determines the width for the each column. You can normalize the column widths by specifying a size large enough to hold the widest label. Alternatively, you can calculate—using Struts and JSTL—a uniform percentage for the width—which you can apply to each column.

You use the Struts `bean:size` tag to create a scoped variable whose value is the number of columns. Then use a JSTL expression to turn that value into a percentage:

```<bean:size id="cols" name="weeklyWeather" property="weekForecast"/>
<tr align="center" height="10%">
<logic:iterate id="dayEntry" name="weeklyWeather" property="weekForecast">
<td align="center" width="<c:out value='\${100 div cols}'/>%">
<bean:write name="dayEntry" property="day"/>
</td>
</logic:iterate>
</tr>```