Chart Data

Chart data is stored in a data series model that contains information about the visual representation of the data points in addition to their values. There are a number of different types of series - DataSeries, ListSeries, AreaListSeries, and RangeSeries.

List Series

The ListSeries is essentially a helper type that makes the handling of simple sequential data easier than with DataSeries. The data points are assumed to be at a constant interval on the X axis, starting from the value specified with the pointStart property (default is 0) at intervals specified with the pointInterval property (default is 1.0). The two properties are defined in the PlotOptions for the series.

The Y axis values are given in a List<Number>, or with ellipsis or an array.

ListSeries series = new ListSeries(
      "Total Reindeer Population",
      181091, 201485, 188105, ...);
PlotOptionsLine plotOptions = new PlotOptionsLine();
plotOptions.setPointStart(1959);
series.setPlotOptions(plotOptions);
conf.addSeries(series);

You can also add them one by one with the addData() method, which is typical when converting from some other representation.

// Original representation
int data[][] = reindeerData();

// Create a list series with X values starting from 1959
ListSeries series = new ListSeries("Reindeer Population");
PlotOptionsLine plotOptions = new PlotOptionsLine();
plotOptions.setPointStart(1959);
series.setPlotOptions(plotOptions);

// Add the data points
for (int row[]: data)
    series.addData(row[1]);

conf.addSeries(series);

If the chart has multiple Y axes, you can specify the axis for the series by its index number with setyAxis().

Generic Data Series

The DataSeries can represent a sequence of data points at an interval as well as scatter data. Data points are represented with the DataSeriesItem class, which has x and y properties for representing the data value. Each item can be given a category name.

DataSeries series = new DataSeries();
series.setName("Total Reindeer Population");
series.add(new DataSeriesItem(1959, 181091));
series.add(new DataSeriesItem(1960, 201485));
series.add(new DataSeriesItem(1961, 188105));
series.add(new DataSeriesItem(1962, 177206));

// Modify the color of one point
series.get(2).getMarker().setFillColor(SolidColor.RED);
conf.addSeries(series);

Data points are associated with some visual representation parameters: marker style, selected state, legend index, and dial style (for gauges). Most of them can be configured at the level of individual data series items, the series, or in the overall plot options for the chart. The configuration options are described in "Chart Configuration". Some parameters, such as the sliced option for pie charts is only meaningful to configure at item level.

Adding and Removing Data Items

New DataSeriesItem items are added to a series with the add() method. The basic method takes just the data item, but the other method takes also two boolean parameters. If the updateChart parameter is false, the chart is not updated immediately. This is useful if you are adding many points in the same request.

The shift parameter, when true, causes removal of the first data point in the series in an optimized manner, thereby allowing an animated chart that moves to left as new points are added. This is most meaningful with data with even intervals.

You can remove data points with the remove() method in the series. Removal is generally not animated, unless a data point is added in the same change, as is caused by the shift parameter for the add().

Updating Data Items

If you update the properties of a DataSeriesItem object, you need to call update() method for the series with the item as the parameter. Changing the coordinates of a data point in this way causes animation of the change.

Range Data

Range charts expect the Y values to be specified as minimum-maximum value pairs. The DataSeriesItem provides setLow() and setHigh() methods to set the minimum and maximum values of a data point, as well as a number of constructors that accept the values.

RangeSeries series =
    new RangeSeries("Temperature Extremes");

// Give low-high values in constructor
series.add(new DataSeriesItem(0, -51.5, 10.9));
series.add(new DataSeriesItem(1, -49.0, 11.8));

// Set low-high values with setters
DataSeriesItem point = new DataSeriesItem();
point.setX(2);
point.setLow(-44.3);
point.setHigh(17.5);
series.add(point);

The RangeSeries offers a slightly simplified way of adding ranged data points, as described in Range Series.

Range Series

The RangeSeries is a helper class that extends DataSeries to allow specifying interval data a bit easier, with a list of minimum-maximum value ranges in the Y axis. You can use the series in range charts, as described in "Area and Column Range Charts".

For X axis, the coordinates are generated at fixed intervals starting from the value specified with the pointStart property (default is 0) at intervals specified with the pointInterval property (default is 1.0).

Setting the Data

The data in a RangeSeries is given as an array of minimum-maximum value pairs for the Y value axis. The pairs are also represented as arrays. You can pass the data using the ellipsis in the constructor or the setData():

RangeSeries series =
    new RangeSeries("Temperature Ranges",
    new Double[]{-51.5,10.9},
    new Double[]{-49.0,11.8},
    ...
    new Double[]{-47.0,10.8});
conf.addSeries(series);

Or, as always with variable arguments, you can also pass them in an array, in the following for the setData():

series.setRangeData(new Double[][] {
    new Double[]{-51.5,10.9},
    new Double[]{-49.0,11.8},
    ...
    new Double[]{-47.0,10.8}});

Container Data Series

The ContainerDataSeries is an adapter for binding Vaadin Container data sources to charts. The container needs to have properties that define the name, X-value, and Y-value of a data point. The default property IDs of the three properties are " name", " x", and " y", respectively. You can set the property IDs with setNamePropertyId(), setYPropertyId(), and setXPropertyId(), respectively. If the container has no x property, the data is assumed to be categorical.

In the following example, we have a BeanItemContainer with Planet items, which have a name and diameter property. We display the container data both in a Vaadin Table and a chart.

// The data
BeanItemContainer<Planet> container =
        new BeanItemContainer<Planet>(Planet.class);
container.addBean(new Planet("Mercury", 4900));
container.addBean(new Planet("Venus", 12100));
container.addBean(new Planet("Earth", 12800));
...

// Display it in a table
Table table = new Table("Planets", container);
table.setPageLength(container.size());
table.setVisibleColumns("name","diameter");
layout.addComponent(table);

// Display it in a chart
Chart chart = new Chart(ChartType.COLUMN);
... Configure it ...

// Wrap the container in a data series
ContainerDataSeries series =
        new ContainerDataSeries(container);

// Set up the name and Y properties
series.setNamePropertyId("name");
series.setYPropertyId("diameter");

conf.addSeries(series);

As the X axis holds categories rather than numeric values, we need to set up the category labels with an array of string. There are a few ways to do that, some more efficient than others, below is one way:

// Set the category labels on the axis correspondingly
XAxis xaxis = new XAxis();
String names[] = new String[container.size()];
List<Planet> planets = container.getItemIds();
for (int i=0; i<planets.size(); i++)
    names[i] = planets.get(i).getName();
xaxis.setCategories(names);
xaxis.setTitle("Planet");
conf.addxAxis(xaxis);

The result can be seen in Table and Chart Bound to a Container.

Table and Chart Bound to a Container

Drill-Down

Vaadin Charts allows drilling down from a chart to a more detailed view by clicking an item in the top-level view. To enable the feature, you need to provide a separate data series for each of the detailed views by calling the addItemWithDrilldown() method. When the user clicks on a drill-down item, the current series is animated into the the linked drill-down series. A customizable back button is provided to navigate back to the main series, as shown in Detailed series after a drill-down.

Detailed series after a drill-down

There are two ways to use drill-down: synchronous and asynchronous.

Synchronous

When using synchronous drill-down, you provide the top-level series and all the series below it beforehand. The data is transferred to the client-side at the same time and no client-server communication needs to happen for the drill-down. The drill-down series must have an identifier, set with setId(), as shown below.

DataSeries series = new DataSeries();

DataSeriesItem mainItem = new DataSeriesItem("MSIE", 55.11);

DataSeries drillDownSeries = new DataSeries("MSIE versions");
drillDownSeries.setId("MSIE");

drillDownSeries.add(new DataSeriesItem("MSIE 6.0", 10.85));
drillDownSeries.add(new DataSeriesItem("MSIE 7.0", 7.35));
drillDownSeries.add(new DataSeriesItem("MSIE 8.0", 33.06));
drillDownSeries.add(new DataSeriesItem("MSIE 9.0", 2.81));

series.addItemWithDrilldown(mainItem, drillDownSeries);

Asynchronous

When using asynchronous drill-down, you omit the drill-down series parameter. Instead, you provide a callback method with Chart.setDrillDownCallback(). When the user clicks an item in the series, the callback is called to provide a drill-down series.

DataSeries series = new DataSeries();

DataSeriesItem mainItem = new DataSeriesItem("MSIE", 55.11);

series.addItemWithDrilldown(mainItem);

chart.setDrilldownCallback(new DrilldownCallback() {
    @Override
    public Series handleDrilldown(DrilldownEvent event) {
        DataSeries drillDownSeries = new DataSeries("MSIE versions");

        drillDownSeries.add(new DataSeriesItem("MSIE 6.0", 10.85));
        drillDownSeries.add(new DataSeriesItem("MSIE 7.0", 7.35));
        drillDownSeries.add(new DataSeriesItem("MSIE 8.0", 33.06));
        drillDownSeries.add(new DataSeriesItem("MSIE 9.0", 2.81));

        return drillDownSeries;
    }
});

You can use the event to decide what kind of series you want to return. The event contains, for example, a reference to the item that was clicked. Note that the same callback is used for all items. The callback can also return null. Returning null will not trigger a drilldown.