使用 spring boot, thymeleaf, js, highchart 绘制饼图但不能

Draw pie chart using spring boot, thymeleaf, js, highchart but can't

我是 js 和 spring 的新手,现在我想创建一个 html 仪表板,此页面将有一个带有饼图的小 div。但我无法创建饼图。 我在 youtube 上尝试了一些教程,但现在我想将值传递给 ajax 或类似的东西来获取饼图。 这是我的代码: admin_homepage.html:

<div class="col-xl-4 col-lg-5">
                    <div class="card shadow mb-4">
                        <!-- Thay chart vào thẻ div này -->
                        <div class="card-body">
                            <div class="chart-pie pt-4 pb-2">
                                <div id="chartContainer" style="height: 370px; width: 100%;"></div> 
                            </div>
                        </div>
                    </div>
                </div>

<script type="text/javascript">
    $.ajax({
        /* for pie chart */
        url: "admin_home",

        success: function(result){
            /* pie chart starts here */
            var series = [];
            var data = [];

            for(var i = 0; i < result.length; i++){
                var object = {};
                object.name = result[i].catName.toUpperCase();
                object.y = result[i].catCount;
                data.push(object);
            }
            var seriesObject = {
                name: 'Course By Category',
                colorByPoint: true,
                data: data
            };
            series.push(seriesObject);
            drawPieChart(series);

            /* pie chart ends here */
        }
    });

    /* for pie chart */
    function drawPieChart(series){
        Highcharts.chart('chartContainer', {
            chart: {
                plotBackgroundColor: null,
                plotBorderWidth: null,
                plotShadow: false,
                type: 'pie'
            },
            title: {
                text: 'Browser market shares in January, 2018'
            },
            tooltip: {
                formatter: function() {
                    return '<strong>'+this.key+': </strong>'+ this.y;
                }
            },
            plotOptions: {
                pie: {
                    allowPointSelect: true,
                    cursor: 'pointer',
                    dataLabels: {
                        enabled: true,
                        format: '<b>{point.name}</b>: {point.y}'
                    }
                }
            },
            series: series
        });
    }

</script>

我的控制器

@GetMapping("/admin_home")
public String viewHomePage(){
 // Get list of course and count
        List<CountCourse> pieChart = dashBoardRepository.countCourseByCategory();

        model.addAttribute("pieChart",pieChart);
        return "Admin_Homepage";
}

我只想将 catName、catCount 的值传递给饼图,但我做不到 任何人帮助我。非常感谢。

因为您使用的是 Thymeleaf 模板,所以您不需要使用 $.ajax({...}) 来检索饼图数据。相反,您可以直接向 Thymeleaf 模板提供数据。

(或者,您可以继续使用 Ajax 调用 - 在这种情况下,Thymeleaf 模板将呈现为 HTML - 然后作为单独的步骤,Ajax 调用将获取饼图数据。)

以下假定第一种方法(不需要 Ajax):

不需要Ajax

我在问题中使用了您的 Thymeleaf 模板并对脚本进行了一些更改:

  1. 我删除了 Ajax 调用。

  2. 我添加了一个 Thymeleaf 变量来保存图表数据。

这是更新后的脚本:

<script th:inline="javascript">

    // this simply wraps the code in a function
    // that waits for the DOM to be ready:
    (function () {

        // this is populated by Thymeleaf:
        var pieChartData = /*[[${pieChartData}]]*/ [];

        var series = [];
        var data = [];

        for (var i = 0; i < pieChartData.length; i++) {
            var object = {};
            object.name = pieChartData[i].catName.toUpperCase();
            object.y = pieChartData[i].catCount;
            data.push(object);
        }
        var seriesObject = {
            name: 'Course By Category',
            colorByPoint: true,
            data: data
        };
        series.push(seriesObject);
        drawPieChart(series);

        // draw the pie chart:
        function drawPieChart(series) {
            Highcharts.chart('chartContainer', {
                chart: {
                    plotBackgroundColor: null,
                    plotBorderWidth: null,
                    plotShadow: false,
                    type: 'pie'
                },
                title: {
                    text: 'Your Heading Goes Here'
                },
                tooltip: {
                    formatter: function () {
                        return '<strong>' + this.key + ': </strong>' + this.y;
                    }
                },
                plotOptions: {
                    pie: {
                        allowPointSelect: true,
                        cursor: 'pointer',
                        dataLabels: {
                            enabled: true,
                            format: '<b>{point.name}</b>: {point.y}'
                        }
                    }
                },
                // use the series data defined earlier:
                series: series
            });
        }

    })();

</script>

这个脚本的要点是:

  1. 脚本标签如下所示:
<script th:inline="javascript">

这告诉 Thymeleaf 脚本将包含一个或多个 Thymeleaf 表达式。

在我们的例子中,我们有一个表达式 - 这里是:

var pieChartData = /*[[${pieChartData}]]*/ [];

此语法将导致 Thymeleaf 将 pieChartData 变量替换为 Java 控制器提供的数据结构。

这是来自控制器的那篇文章:

List<CountCourse> pieChartData = dashBoardRepository.countCourseByCategory();
model.addAttribute("pieChartData", pieChartData);
return "admin_homepage";

这假设您有一个包含 String catNameint catCountCountCourse 对象。

Thymeleaf 将获取 List<CountCourse> pieChartData 数据并为您生成以下 Java 脚本(使用我的测试数据):

var pieChartData = [
  {"catName":"Humanities","catCount":123},
  {"catName":"Sciences","catCount":145},
  {"catName":"Other","catCount":67}
];

之后,我使用与您在 Ajax 成功函数中相同的逻辑将此原始数据转换为 HightCharts 饼图数据。

最终结果如下 HTML 页:

和Ajax

如果你想使用你的 Ajax 方法而不是这个,那么你需要构建一个单独的端点,它将 return 饼图数据直接发送到 Ajax 处理程序在你的Java脚本代码中。

当您采用这种方法时,您不再需要使用 Thymeleaf 属性:

var pieChartData = /*[[${pieChartData}]]*/ []; // NO LONGER NEEDED

并且您不再需要将此数据传递给控制器​​中的模型:

model.addAttribute("pieChartData", pieChartData); // NO LONGER NEEDED

相反,您需要继续使用您的 $.ajax 代码,并且您需要构建一个单独的端点,其中 return 将 pieChartData 作为 JSON Ajax 通话:

$.ajax({
  /* for pie chart */
  url: "piechart_data_json", // some new URL for your JSON pie chart data
  ...
});

鉴于您已经在使用 Thymeleaf,我认为没有必要使用这种方法。


更新

只是稍微解释一下下面的语法:

var pieChartData = /*[[${pieChartData}]]*/ [];

它看起来像一个空的 Java脚本数组 []。但事实上,还有更多。

Thymeleaf 变量 ${pieChartData} 从控制器接收数据。

因为变量位于 <script> 标记中,仅使用标准的 Thymeleaf ${pieChartData} 表达式是不够的。您还必须用 [[]] 包围该表达式。这是因为 ${pieChartData} 实际上是有效的 Java 脚本 - 例如,用于字符串插值。

这给了我们这个:

var pieChartData = [[${pieChartData}]];

这就是您所需要的。这会起作用。

这里的问题是,它不是有效的 Java脚本,因此您的 IDE 可能会突出显示它存在语法错误。

要解决此问题,您可以采取额外的步骤。您可以在 Java 脚本注释中“隐藏”表达式 - 然后提供有效值(空数组)。这使 JavaScript 语法检查器在您的 IDE.

中保持快乐

Thymeleaf 将在该注释中找到变量并将其删除 - 同时删除占位符 [] 值。

在这种情况下,这就是 Thymeleaf 将 Java 模型数据推送到模板中的方式。