Spring Boot Thymeleaf here. I have the following static HTML file that I've been testing with:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<script>
window.onload = function() {
var foodChart = new CanvasJS.Chart("foodChart", {
animationEnabled: true,
title: {
text: "Foods"
},
data: [{
type: "pie",
startAngle: 240,
yValueFormatString: "##0.00\"%\"",
indexLabel: "{label} {y}",
dataPoints: [
{y: 95.0, label: "Pizza"},
{y: 5.0, label: "French Fries"}
]
}]
});
foodChart.render();
}
</script>
</head>
<body>
<div id="foodChart" style="height: 300px; width: 100%;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
This opens in a browser and works just great, Pie Chart and all.
But now I want to make the Pie Chart dynamic and I want the server to set the values of all the slices in the Pie Chart. So on the server-side (Java/Spring Boot), I have:
Map<String,BigDecimal> foodMap = new HashMap<>();
foodMap.put("Pizza", BigDecimal.valueOf(35.0)); // 35%
foodMap.put("French Fries", BigDecimal.valueOf(65.0)); // 65%
And I'm trying to figure out how to modify the HTML file (template) with Thymeleaf tags so that I can use this foodMap
to drive the slices of the Pie Chart, dynamically. I think I need something like:
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<script>
window.onload = function() {
var foodChart = new CanvasJS.Chart("foodChart", {
animationEnabled: true,
title: {
text: "Foods"
},
data: [{
type: "pie",
startAngle: 240,
yValueFormatString: "##0.00\"%\"",
indexLabel: "{label} {y}",
dataPoints: [
<th:each="key: ${foodMap}">
{<th:text="y: ${value}, label: ${key}" />}
</th>
]
}]
});
foodChart.render();
}
</script>
</head>
<body>
<div id="foodChart" style="height: 300px; width: 100%;"></div>
<script src="https://canvasjs.com/assets/script/canvasjs.min.js"></script>
</body>
</html>
But this doesn't work, can anyone nudge me in the right direction?
CodePudding user response:
You should take advantage of Thymeleaf's JavaScript inlining for this. For example, if you do this:
<script th:inline="javascript">
let foodMap = /*[[${foodMap}]]*/ {};
</script>
It will output:
<script>
let foodMap = {"Pizza":35.0,"French Fries":65.0};
</script>
Once you have this data, it's pretty easy to convert it to the format you want. Putting it all together:
<script th:inline="javascript">
window.onload = function() {
let foodMap = /*[[${foodMap}]]*/ {};
let dataPoints = [];
for (food in foodMap) {
dataPoints.push({
'label': food,
'y': foodMap[food]
});
};
var foodChart = new CanvasJS.Chart("foodChart", {
animationEnabled: true,
title: {text: "Foods"},
data: [{
type: "pie",
startAngle: 240,
yValueFormatString: "##0.00\"%\"",
indexLabel: "{label} {y}",
dataPoints: dataPoints
}]
});
foodChart.render();
}
</script>