Chart Js 无法读取未定义的属性'length'。

19

使用Chart js,我正在尝试从Ajax调用中提取数据以供图表使用。

我发现其他一些帖子中的人建议延迟canvas加载,但似乎没有任何作用。目前,以下是我的代码,我收到的错误消息是:

输入图像描述

$(function () {

GetChartData();

    function GetChartData() {
    $.ajax({
        url: ajaxURL,
        method: 'GET',
        dataType: 'json',
        success: function (d) {
            //-------------
            //- BAR CHART -
            //-------------
            var barChartData = d;
            var barChartCanvas = $("#barChart").get(0).getContext("2d");
            var barChart = new Chart(barChartCanvas);
            // console.log(datajson);
            //barChartData.datasets[1].fillColor = "#00a65a";
            //barChartData.datasets[1].strokeColor = "#00a65a";
            //barChartData.datasets[1].pointColor = "#00a65a";
            var barChartOptions = {
                //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
                //scaleBeginAtZero: true,
                //Boolean - Whether grid lines are shown across the chart
                scaleShowGridLines: true,
                //String - Colour of the grid lines
                scaleGridLineColor: "rgba(0,0,0,.05)",
                //Number - Width of the grid lines
                scaleGridLineWidth: 1,
                //Boolean - Whether to show horizontal lines (except X axis)
                scaleShowHorizontalLines: true,
                //Boolean - Whether to show vertical lines (except Y axis)
                scaleShowVerticalLines: true,
                //Boolean - If there is a stroke on each bar
                barShowStroke: true,
                //Number - Pixel width of the bar stroke
                barStrokeWidth: 2,
                //Number - Spacing between each of the X value sets
                barValueSpacing: 5,
                //Number - Spacing between data sets within X values
                barDatasetSpacing: 1,
                multiTooltipTemplate: "<%=datasetLabel%>: <%= value + ' %' %>",
                //String - A legend template
                legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
                //Boolean - whether to make the chart responsive
                responsive: true,
                maintainAspectRatio: true
            };


            barChartOptions.datasetFill = false;
            barChart.Bar(barChartData, barChartOptions);


        }
    });
    }
});

更新此处以展示如何使用非Ajax工作

以下代码将获取的Ajax请求结果(从控制台转储获得)并创建了一个“硬编码”版本的相同结果。在页面加载时,唯一可能不同的是一个数据已经加载,而另一个数据稍后会被加载。

 var chartData = {
    "labels": [
      "April"
    ],
    "datasets": [
      {
          "label": "Not Sure What to Put Here",
          "fillColor": "#662B60",
          "strokeColor": "#662B60",
          "pointColor": "#662B60",
          "pointStrokeColor": "#662B60",
          "pointHighlightFill": "#662B60",
          "pointHighlightStroke": "#662B60",
          "data": [
            1
          ]
      },
      {
          "label": "Not Sure What to Put Here",
          "fillColor": "#88B56E",
          "strokeColor": "#88B56E",
          "pointColor": "#88B56E",
          "pointStrokeColor": "#88B56E",
          "pointHighlightFill": "#88B56E",
          "pointHighlightStroke": "#88B56E",
          "data": [
            1
          ]
      },
      {
          "label": "Not Sure What to Put Here",
          "fillColor": "#48CA2B",
          "strokeColor": "#48CA2B",
          "pointColor": "#48CA2B",
          "pointStrokeColor": "#48CA2B",
          "pointHighlightFill": "#48CA2B",
          "pointHighlightStroke": "#48CA2B",
          "data": [
            0.83
          ]
      }
    ]
};


    //-------------
    //- BAR CHART -
    //-------------
var barChartData = chartData;
    var barChartCanvas = $("#barChart").get(0).getContext("2d");
    var barChart = new Chart(barChartCanvas);

    //barChartData.datasets[1].fillColor = "#00a65a";
    //barChartData.datasets[1].strokeColor = "#00a65a";
    //barChartData.datasets[1].pointColor = "#00a65a";
    var barChartOptions = {
        //Boolean - Whether the scale should start at zero, or an order of magnitude down from the lowest value
        //scaleBeginAtZero: true,
        //Boolean - Whether grid lines are shown across the chart
        scaleShowGridLines: true,
        //String - Colour of the grid lines
        scaleGridLineColor: "rgba(0,0,0,.05)",
        //Number - Width of the grid lines
        scaleGridLineWidth: 1,
        //Boolean - Whether to show horizontal lines (except X axis)
        scaleShowHorizontalLines: true,
        //Boolean - Whether to show vertical lines (except Y axis)
        scaleShowVerticalLines: true,
        //Boolean - If there is a stroke on each bar
        barShowStroke: true,
        //Number - Pixel width of the bar stroke
        barStrokeWidth: 2,
        //Number - Spacing between each of the X value sets
        barValueSpacing: 5,
        //Number - Spacing between data sets within X values
        barDatasetSpacing: 1,
        multiTooltipTemplate: "<%=datasetLabel%>: <%= value + ' %' %>",
        //String - A legend template
        legendTemplate: "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].fillColor%>\"></span><%if(datasets[i].label){%><%=datasets[i].label%><%}%></li><%}%></ul>",
        //Boolean - whether to make the chart responsive
        responsive: true,
        maintainAspectRatio: true
    };


    barChartOptions.datasetFill = false;
    barChart.Bar(barChartData, barChartOptions);

更新:我从chart.js的min版本更改为完整版本,以便我可以看到它确切地出错的位置。

这是来自Chrome控制台的图像输入图像描述


你应该验证从 AJAX 调用中获取的数据是否符合你期望的格式。我猜测在查看错误后,Chart.js 没有以某种方式接收到任何数据(或者格式不正确)。 - AlbertEngelB
你应该将 datasets 替换为 barChartData,对吗? - Christian Phillips
所以我应该把这个加到问题里。我将数据转储到控制台,以便查看它。然后我复制了那些数据,并为其创建了一个虚拟变量,并将该变量分配给图表。因此,我硬编码了数据,它可以工作,所以我只能假设它与ajax调用本身有关。 - scripter78
我本可以直接使用barChart.Bar(d, barChartOptions);,但我想尽可能地保持与我正在使用的示例的接近。 - scripter78
如果有人从谷歌搜索进入这里,看到在谷歌图表可视化中出现相同的错误,请尝试更改图表大小。实际上,我之所以会遇到这个错误,是因为我将我的图表包装在 Bootstrap 类 card 中,这使得容器太小了。这实际上导致了 Google Charts 中的这个错误,在 Chrome 控制台中没有错误。呼.. - jonathanbell
它正在查找 labels.length,而你已将键指定为 label。因此,labels 实际上未定义。 - Kinjal Dixit
8个回答

17
问题在于当您的代码执行时,画布还未被创建。 您应该将代码包装在一个函数内,并将该函数赋值给window.onload事件。以下是示例代码。

问题在于当您的代码执行时,画布还未被创建。 您应该将代码包装在一个函数内,并将该函数赋值给window.onload事件。以下是示例代码。

window.onload = function() {
  var ctx = document.getElementById("myChart");
  var lineChart = new Chart(ctx, {
    type: 'line',
    data: {
      labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
      datasets: [{
        label: "2015",
        data: [10, 8, 6, 5, 12, 8, 16, 17, 6, 7, 6, 10]
      }]
    }
  })
}
<html>

<head>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.js"></script>

</head>

<body>
  <canvas id="myChart"></canvas>
</body>

</html>


最佳答案,伙计。 - Ricardo

6

找到了答案,

Ajax结果必须先进行解析。

修复结果。

var barChartData = JSON.parse(d);

4
对于其他遇到此问题的用户,请确保在调用时容器画布元素已存在。

4

以下命令对我有效:

window.onload = function () {

}

2
您可以尝试将Chart.JS脚本标签和其他自定义JS脚本放在**<**/body>标签的末尾。

0

这是一个旧问题,我也遇到了这个问题,在我的情况下,我的数据长度为0。我解决了这个问题,只需在调用图表之前添加验证:

if (barChartData.length > 0)
{
   objChart = Morris.Bar({....
}

0

看起来您正在使用一个不存在的对象,至少我看不到它,datasets。 我只能看到该对象上调用了length,除非缺少代码?

我可以看到您将d分配给barChartData

var barChartData = d;

因此,您可能希望将datasets的实例替换为barChartData


0

我在下载并使用一个免费的Bootstrap 5管理模板时,遇到了同样的错误,该模板使用了Chart JS包。

Chart.min.js:7 Uncaught TypeError: Cannot read properties of null (reading 'length')
    at Object.acquireContext (Chart.min.js:7:76631)
    at ni.construct (Chart.min.js:7:92209)
    at new ni (Chart.min.js:7:91964)
    at chart-area-demo.js:7:19

在我的控制台中:

enter image description here

这是初始代码:

// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#292b2c';

// Area Chart Example
var ctx = document.getElementById("myAreaChart");
var myLineChart = new Chart(ctx, {
    type: 'line',
    data: {
        labels: ["Mar 1", "Mar 2", "Mar 3", "Mar 4", "Mar 5", "Mar 6", "Mar 7", "Mar 8", "Mar 9", "Mar 10", "Mar 11", "Mar 12", "Mar 13"],
        datasets: [{
            label: "Sessions",
            lineTension: 0.3,
            backgroundColor: "rgba(2,117,216,0.2)",
            borderColor: "rgba(2,117,216,1)",
            pointRadius: 5,
            pointBackgroundColor: "rgba(2,117,216,1)",
            pointBorderColor: "rgba(255,255,255,0.8)",
            pointHoverRadius: 5,
            pointHoverBackgroundColor: "rgba(2,117,216,1)",
            pointHitRadius: 50,
            pointBorderWidth: 2,
            data: [10000, 30162, 26263, 18394, 18287, 28682, 31274, 33259, 25849, 24159, 32651, 31984, 38451],
        }],
    },
    options: {
        scales: {
            xAxes: [{
                time: {
                    unit: 'date'
                },
                gridLines: {
                    display: false
                },
                ticks: {
                    maxTicksLimit: 7
                }
            }],
            yAxes: [{
                ticks: {
                    min: 0,
                    max: 40000,
                    maxTicksLimit: 5
                },
                gridLines: {
                    color: "rgba(0, 0, 0, .125)",
                }
            }],
        },
        legend: {
            display: false
        }
    }
});

所以我做的是通过使用条件(IF)添加一个简单的存在验证。像这样:

// Set new default font family and font color to mimic Bootstrap's default styling
Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif';
Chart.defaults.global.defaultFontColor = '#292b2c';

// Area Chart Example
var ctx = document.getElementById("myAreaChart");
if (ctx) {
    var myLineChart = new Chart(ctx, {
        type: 'line',
        data: {
            labels: ["Mar 1", "Mar 2", "Mar 3", "Mar 4", "Mar 5", "Mar 6", "Mar 7", "Mar 8", "Mar 9", "Mar 10", "Mar 11", "Mar 12", "Mar 13"],
            datasets: [{
                label: "Sessions",
                lineTension: 0.3,
                backgroundColor: "rgba(2,117,216,0.2)",
                borderColor: "rgba(2,117,216,1)",
                pointRadius: 5,
                pointBackgroundColor: "rgba(2,117,216,1)",
                pointBorderColor: "rgba(255,255,255,0.8)",
                pointHoverRadius: 5,
                pointHoverBackgroundColor: "rgba(2,117,216,1)",
                pointHitRadius: 50,
                pointBorderWidth: 2,
                data: [10000, 30162, 26263, 18394, 18287, 28682, 31274, 33259, 25849, 24159, 32651, 31984, 38451],
            }],
        },
        options: {
            scales: {
                xAxes: [{
                    time: {
                        unit: 'date'
                    },
                    gridLines: {
                        display: false
                    },
                    ticks: {
                        maxTicksLimit: 7
                    }
                }],
                yAxes: [{
                    ticks: {
                        min: 0,
                        max: 40000,
                        maxTicksLimit: 5
                    },
                    gridLines: {
                        color: "rgba(0, 0, 0, .125)",
                    }
                }],
            },
            legend: {
                display: false
            }
        }
    });
}

之后不会再有错误了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接