Reputation: 1799
I need to build a Highcharts pie chart with data from a Java backing bean in a JSF page.
I need to know what must be passed as the data
attribute of series
:
series: [{
type: 'pie',
name: 'Browser share',
data: [
['Firefox', 45.0],
['IE', 26.8],
{
name: 'Chrome',
y: 12.8,
sliced: true,
selected: true
},
['Safari', 8.5],
['Opera', 6.2],
['Others', 0.7]
]
}]
I suppose it's an array of arrays. Tried passing Map<String, Double>
, List<Map<String, Double>>
, Map<List<String>,List<Double>>
. The last try was the list of maps (this code is inside a method annotated with @PostConstruct
so it's executed after the constructor:
this.mapPie = new HashMap<>();
this.mapPie.put("Column 1", 3.0);
this.mapPie.put("Column 2", 8.5);
this.mapPie.put("Column 3", 6.0);
this.mapPie.put("Column 4", 15.0);
this.mapPie.put("Column 5", 9.0);
this.mapPie.put("Column 6", 6.5);
this.listMapPie = new ArrayList<>();
mapPie.entrySet().stream().forEach((Map.Entry<String, Double> pairs) -> {
String key = pairs.getKey();
Double value = pairs.getValue();
Map<String, Double> m = new HashMap<>();
m.put(key, value);
this.listMapPie.add(m);
});
All getters and setters were created, but none of those objects work and a page reload happens.
XHTML:
<h:form>
<p:panelGrid columns="2">
<p:commandButton icon="ui-icon-extlink" value="Pie" onclick="gerarGraficoPizza('title', 'seriesName', #{chartBean.listMapPie})">
<p:ajax event="click" update="pie" />
</p:commandButton>
<div jsf:id="pie" id="pie" style="min-width: 400px; max-width: 600px; height: 400px; margin: 0 auto"></div>
</p:panelGrid>
</h:form>
JavaScript:
//<![CDATA[
function gerarGraficoPizza(title, seriesName, seriesData) {
$('#pie').highcharts({
chart: {
plotBackgroundColor: null,
plotBorderWidth: 1, //null,
plotShadow: false
},
title: {
text: title
},
tooltip: {
pointFormat: '{series.name}: <b>{point.percentage:.1f}%</b>'
},
plotOptions: {
pie: {
allowPointSelect: true,
cursor: 'pointer',
dataLabels: {
enabled: true,
format: '<b>{point.name}</b>: {point.percentage:.1f} %',
style: {
color: (Highcharts.theme && Highcharts.theme.contrastTextColor) || 'black'
}
}
}
},
series: [{
type: 'pie',
name: seriesName,
data: seriesData
}]
});
}
//]]>
EDIT:
Modified the Java code and now the list of maps was filled, but same result in the page:
this.listMapPie = new ArrayList<>();
this.mapPie = new HashMap<>();
this.mapPie.put("Column 1", 3.0);
this.listMapPie.add(this.mapPie);
this.mapPie = new HashMap<>();
this.mapPie.put("Column 2", 8.5);
this.listMapPie.add(this.mapPie);
this.mapPie = new HashMap<>();
this.mapPie.put("Column 3", 6.0);
this.listMapPie.add(this.mapPie);
this.mapPie = new HashMap<>();
this.mapPie.put("Column 4", 15.0);
this.listMapPie.add(this.mapPie);
this.mapPie = new HashMap<>();
this.mapPie.put("Column 5", 9.0);
this.listMapPie.add(this.mapPie);
this.mapPie = new HashMap<>();
this.mapPie.put("Column 6", 6.5);
this.listMapPie.add(this.mapPie);
Upvotes: 1
Views: 1484
Reputation: 1108852
That's JSON format. You're trying to pass List#toString()
and Map#toString()
as if it's already JSON format. This isn't right. You need a JSON printer. At bottom of json.org page you can find several JSON APIs which supports both parsing and printing. One of them is Google Gson. Install it (just put JAR in webapp's runtime classpath, usually by dropping in /WEB-INF/lib
).
Once done that, just do
listMapPieAsJson = new Gson().toJson(listMapPie);
onclick="gerarGraficoPizza('title', 'seriesName', #{chartBean.listMapPieAsJson})"
As to the format of listMapPie
, you were close. The supported formats are just listed in their documentation. Let's assume that you want an array of objects with named values (which is way 3 as shown in documentation). In order to achieve the desired JSON format from Java side on, you only need to know those 2 rules:
[]
is an array in JSON and can in Java be presented by List<T>
or T[]
.{}
is an object in JSON and can in Java be presented by Map<K, V>
or a Bean
which is a true Javabean class with getters/setters.Your mistake was that you used the column name directly as map key instead of setting it along with name
as key.
listMapPie = new ArrayList<>();
Map<String, Object> mapPie;
mapPie = new HashMap<>();
mapPie.put("name", "Column 1")
mapPie.put("y", 3.0);
listMapPie.add(mapPie);
mapPie = new HashMap<>();
mapPie.put("name", "Column 2")
mapPie.put("y", 8.5);
listMapPie.add(mapPie);
mapPie = new HashMap<>();
mapPie.put("name", "Column 3")
mapPie.put("y", 6.0);
listMapPie.add(mapPie);
// Etc..
listMapPieAsJson = new Gson().toJson(listMapPie);
An alternative is to create a simple Javabean class:
public class Pie {
private String name;
private double y;
// Add/generate c'tors/getters/setters/equals/hashCode.
}
So that you can just do
listMapPie = new ArrayList<>();
listMapPie.add(new Pie("Column 1", 3.0));
listMapPie.add(new Pie("Column 2", 8.5));
listMapPie.add(new Pie("Column 3", 6.0));
// Etc..
listMapPieAsJson = new Gson().toJson(listMapPie);
Upvotes: 1