You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot+Thymeleaf:如何在JS中遍历Map生成动态饼图

问题:Spring Boot + Thymeleaf 实现 CanvasJS 饼图动态数据渲染

我用Spring Boot搭配Thymeleaf开发项目,之前静态HTML能正常渲染CanvasJS饼图,现在需要让饼图数据从后端的foodMap(存储食物名称与占比的BigDecimal值)动态生成。尝试在JavaScript的dataPoints数组中用Thymeleaf的th:each遍历Map,但写法无效,求正确实现方式。

相关代码

静态HTML代码(可正常渲染静态饼图)

<!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>

后端Java代码

Map<String,BigDecimal> foodMap = new HashMap<>();
foodMap.put("Pizza", BigDecimal.valueOf(35.0)); // 35%
foodMap.put("French Fries", BigDecimal.valueOf(65.0)); // 65%

尝试的无效模板代码

<!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>

解决方案

核心修正点

  1. 正确遍历Map:Thymeleaf遍历Map时需通过entry对象获取键值对,语法为th:each="entry, entryStat : ${foodMap}",其中entry.key是食物名称,entry.value是占比数值;entryStat用于判断是否为最后一个元素,避免生成多余逗号导致JavaScript语法错误。
  2. 格式匹配JSON:生成的dataPoints元素要符合JavaScript对象格式,label值需加引号,BigDecimal值要转为JavaScript可识别的数值类型。

完整正确模板代码

<!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: [
                        <!-- 遍历Map的entry对象,同时获取状态变量判断是否为最后一个元素 -->
                        <th:each="entry, entryStat : ${foodMap}">
                            {y: [[${entry.value.doubleValue()}]], label: "[[${entry.key}]]"}
                            <!-- 最后一个元素不添加逗号 -->
                            <th:if="!${entryStat.last}">,</th:if>
                        </th:each>
                    ]
                }]
            });
            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>

关键说明

  • 使用[[${}]](Thymeleaf内联表达式)替代th:text,更适合在JavaScript代码中直接渲染变量,避免标签嵌套导致的格式问题。
  • 调用entry.value.doubleValue()将BigDecimal转为JavaScript的数值类型,确保饼图能正确识别占比数据。
  • 通过entryStat.last判断是否为最后一个元素,避免在dataPoints数组末尾生成多余逗号,防止JavaScript解析错误。

内容的提问来源于stack exchange,提问作者hotmeatballsoup

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 10:50:22