【问题标题】:Multiple Chart.js Charts in Partial Views Overwriting Each Other部分视图中的多个 Chart.js 图表相互覆盖
【发布时间】:2016-05-03 16:00:33
【问题描述】:

使用 Asp.Net MVC,我正在尝试使用 chart.js 库创建一个在单个页面上显示多个条形图的网页。每个图表都有不同的数据,并在其自己的局部视图中创建。但是,不是创建多个不同的图表,而是最后一个图表数据覆盖页面上的第一个图表,并且所有剩余的图表都显示为空白。如下图所示,“Title and Segments”数据和图例覆盖了“Producers”数据,“Title and Segments”图表为空。

在主视图页面上,我使用 foreach 循环为每个报表呈现相同的局部视图。

@foreach (Report report in Model.Reports)
{
    @Html.Partial("BarChartPartialView", report);
}

在我的局部视图中,我根据模型中的值为画布对象创建了一个动态 ID 名称。这是为了解决Chart.js - Multiple Line Charts - Only Show Last Chart中提到的问题。

@{
    string name = "canvas" + Model.CurrentReport.ID;
}

然后我使用动态 ID 创建一个画布对象。

<canvas id="@name"></canvas>

在我的局部视图中的 chart.js 脚本中,我使用 eval() 创建动态 ctx 和 myBar 变量。 (创意来源:How do i declare and use dynamic variables in javascript?

<script>
    var barChartData = {
        labels: [@Html.Raw(Model.Labels)],
        datasets: [@Html.Raw(Model.Data)]
    };

    $(document).ready(function () {      
        eval("var ctx" + "@name" + "=document.getElementById('@name').getContext('2d');");

        var temp = new Chart(eval('ctx' + '@name'), {
            type: 'bar',
            data: barChartData,
            options: {
                elements: {
                    rectangle: {
                        borderWidth: 2,
                        borderColor: 'rgb(0, 255, 0)'
                    }
                },
                legend: {
                    position: 'bottom'
                },
                title: {
                    display: true,
                    text: '@Model.CurrentReport.Name'
                }
            }
        });

        eval('window.myBar' + '@name' + "= temp;");
    });
</script>

我见过其他类似的问题,但似乎没有一个可以解决我的问题:
multiple chartjs in the same page
Rendering HTML5 Charts in partial views show only blank data

【问题讨论】:

  • 您是否使用 eval 使 ctx 变量名称不同?我认为您使用文档就绪功能解决了这个问题。
  • @AlexanderLindsay 那是我的目标,但它并没有改变任何东西。如果我对所有图表只使用ctx,或者像我目前的尝试一样使用eval(),我会得到同样的混乱结果。

标签: javascript asp.net-mvc partial-views chart.js chart.js2


【解决方案1】:

我认为问题在于barChartData 被每个部分视图覆盖。尝试将该变量放入文档就绪函数中。

或者,使用自执行函数来完成所有图表工作。

(function(){
    var data = {};
})();

基本上,问题在于每个部分视图都将barChartData 的副本添加到页面。每个都在窗口范围内定义。所以页面看起来像这样:

<script>
    var barChartData = {
        labels: ModelOneLabels,
        datasets: ModelOneData
    };
    ...
</script>

<script>
    var barChartData = {
        labels: ModelTwoLabels,
        datasets: ModelTwoData
    };
    ...
</script>

这将给 barChartData 留下模型两个值。

您应该能够查看生成的页面并看到多个脚本标签。您的浏览器开发者工具中的控制台也应该进行验证。

以下是您可以解决的方法:

<script>
    $(document).ready(function () {
        var barChartData = {
            labels: [@Html.Raw(Model.Labels)],
            datasets: [@Html.Raw(Model.Data)]
        };

        var ctx = document.getElementById('@name').getContext('2d');

        // I am not sure how you are using the window.myBar@name var
        // if you are referencing it later than you may need to adjust this part
        var myBar = new Chart(ctx, {
          type: 'bar',
          data: barChartData,
          options: {
              elements: {
                  rectangle: {
                      borderWidth: 2,
                      borderColor: 'rgb(0, 255, 0)',
                      borderSkipped: 'bottom'
                  }
              },
              legend: { 
                  position: 'bottom' 
              }, 
              title: {
                  display: true, 
                  text: '@Model.CurrentReport.Name'
              }
        })

});
</script>

【讨论】:

  • 当你说自执行函数时,你的意思是$(function()};而不是$(document).ready?那会有什么帮助?
  • 目标是在页面上加载第二个局部视图时不覆盖保存数据的变量。
  • barChartData 放在$(document).ready 中就可以了!仍然需要eval() 的东西来让窗口知道 ctx 对象是不同的。从我读到的here$(function{});$(document).ready(function() {}); 是完全相同的,所以改变它不应该有任何区别。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-03
  • 2011-12-23
  • 2015-10-15
  • 1970-01-01
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多