0

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?

1

1 Answer 1

1

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>
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.