Connecting Data
Using DataProvider interface
The DataProvider
interface has two standard implementations: ListDataProvider
class and ContainerDataProvider
class.
An instance of DataProvider
is passed to the setDataProvider()
method of chart configuration. This approach is the most universal, but it requires creating instances of DataProvider
or DataItem
in a screen controller.
Entity properties or the values contained in an instance of DataProvider
which are used for display purposes are defined in the chart attributes. The set of chart attributes may differ for different chart types. For example, for the chart:pieChart
component, you should define the valueField
and titleField
attributes. The following types are allowed for attribute values: Integer
, Long
, Double
, String
, Boolean
, Date
.
ListDataProvider
ListDataProvider
contains a list of the DataItem
instances from which the data for the chart will be taken. There are several standard implementations of the DataItem
interface:
-
EntityDataItem
takes an instance of any entity from which the data for the chart will be taken:@Autowired private PieChart chart; @Autowired private Metadata metadata; @Subscribe protected void onInit(InitEvent event) { ListDataProvider dataProvider = new ListDataProvider(); dataProvider.addItem(new EntityDataItem( (Entity) valueDescription(75, "Sky"))); dataProvider.addItem(new EntityDataItem( (Entity) valueDescription(7, "Shady side of pyramid"))); dataProvider.addItem(new EntityDataItem( (Entity) valueDescription(18, "Sunny side of pyramid"))); chart.setDataProvider(dataProvider); } private ValueDescription valueDescription(Integer value, String description) { ValueDescription entity = metadata.create(ValueDescription.class); entity.setValue(value); entity.setDescription(description); return entity; }
-
MapDataItemScreen
is a set of key-value pairs from which the data for the chart will be taken:@Autowired private PieChart chart; @Subscribe protected void onInit(InitEvent event) { ListDataProvider dataProvider = new ListDataProvider(); dataProvider.addItem(new MapDataItem( ImmutableMap.of("value", 75, "description", "Sky"))); dataProvider.addItem(new MapDataItem( ImmutableMap.of("value", 7, "description", "Shady side of pyramid"))); dataProvider.addItem(new MapDataItem( ImmutableMap.of("value", 18, "description", "Sunny side of pyramid"))); chart.setDataProvider(dataProvider);
-
SimpleDataItem
takes an instance of anypublic
class from which the data for the chart will be taken:@Autowired private PieChart chart; @Subscribe protected void onInit(InitEvent event) { ListDataProvider dataProvider = new ListDataProvider(); dataProvider.addItem(new SimpleDataItem( new ValueDescription(75, "Sky"))); dataProvider.addItem(new SimpleDataItem( new ValueDescription(7, "Shady side of pyramid"))); dataProvider.addItem(new SimpleDataItem( new ValueDescription(18, "Sunny side of pyramid"))); chart.setDataProvider(dataProvider); } public class ValueDescription { private Integer value; private String description; public ValueDescription(Integer value, String description) { this.value = value; this.description = description; } public Integer getValue() { return value; } public String getDescription() { return description; } }
ContainerDataProvider
ContainerDataProvider
is used to assign a CollectionContainer to a Chart
component.
Suppose we have a data container with a loader which will load the TransportCount
instances. Below is the fragment of the screen XML descriptor:
<data>
<collection id="transportCountsDc" class="charts.ex1.entity.TransportCount">
<fetchPlan extends="_base"/>
<loader id="transportCountsDl">
<query>
<![CDATA[select e from sample_TransportCount e order by e.year]]>
</query>
</loader>
</collection>
</data>
<facets>
<dataLoadCoordinator auto="true"/>
</facets>
<layout>
<chart:serialChart id="stackedArea"
categoryField="year"
dataContainer="transportCountsDc"
height="100%"
marginLeft="0"
marginTop="10"
plotAreaBorderAlpha="0"
width="100%">
<!-- ... -->
</chart:serialChart>
</layout>
A screen controller defines the onInit()
method that sets a data provider for the stackedArea
chart. The data provider is based on the transportCountsDc
data container.
@Autowired
private CollectionContainer<TransportCount> transportCountsDc;
@Autowired
private SerialChart stackedArea;
@Subscribe
private void onInit(InitEvent event) {
stackedArea.setDataProvider(new ContainerDataProvider(transportCountsDc));
stackedArea.setCategoryField("year");
}
This approach requires an entity that will represent chart data. It may be convenient when such an entity already exists in the application data model and when chart data should be displayed as a table.
Using Simplified Data Binding
This option is useful for quick prototyping of charts that are not bound to a data container. The chart:data
element and its nested item elements enable you to set key-value pairs of data directly in the XML descriptor of the chart, for example:
<chart:pieChart id="pieChart"
titleField="key"
valueField="value">
<chart:data>
<chart:item>
<chart:property name="key" value="piece of apple pie"/>
<chart:property name="value" value="70" type="int"/>
</chart:item>
<chart:item>
<chart:property name="key" value="piece of blueberry pie"/>
<chart:property name="value" value="20" type="int"/>
</chart:item>
<chart:item>
<chart:property name="key" value="piece of cherry pie"/>
<chart:property name="value" value="10" type="int"/>
</chart:item>
</chart:data>
</chart:pieChart>
Also, you can specify key-value pairs in the screen controller using data binding API.
Add the chart component to the screen and use the addData()
method to fill it with data, passing the MapDataItem
instance with a set of key-value pairs as a parameter:
<chart:pieChart id="pieChart"
titleField="key"
valueField="value"/>
@Autowired
private PieChart pieChart;
@Subscribe
private void onBeforeShow(BeforeShowEvent event) {
pieChart.addData(MapDataItem.of("key", "piece of apple pie",
"value", 70),
MapDataItem.of("key", "piece of blueberry pie",
"value", 20),
MapDataItem.of("key", "piece of cherry pie",
"value", 10));
}