vmpowerio/chartjs-node

Pie charts are broken? Cannot read property 'concat' of undefined

Closed this issue ยท 4 comments

Hi everybody ๐Ÿ‘‹

I'm having an issue on trying to generate some pie/doughnut charts, am I doing something wrong here? The same data works on the live Demo and in my local with other kind of charts, except for the pies :(

This is the error that I get:

Unhandled rejection TypeError: Cannot read property 'concat' of undefined
    at updateConfig (/Users/theBigProject/node_modules/chart.js/src/core/core.controller.js:50:27)
    at Chart.update (/Users/theBigProject/node_modules/chart.js/src/core/core.controller.js:340:4)
    at Chart.construct (/Users/theBigProject/node_modules/chart.js/src/core/core.controller.js:121:7)
    at new Chart (/Users/theBigProject/node_modules/chart.js/src/core/core.js:7:8)
    at jsdom.envAsync.then.window (/Users/theBigProject/node_modules/chartjs-node/index.js:80:31)
    at tryCatcher (/Users/theBigProject/node_modules/chartjs-node/node_modules/bluebird/js/release/util.js:16:23)
    at Promise._settlePromiseFromHandler (/Users/theBigProject/node_modules/chartjs-node/node_modules/bluebird/js/release/promise.js:512:31)
    at Promise._settlePromise (/Users/theBigProject/node_modules/chartjs-node/node_modules/bluebird/js/release/promise.js:569:18)
    at Promise._settlePromise0 (/Users/theBigProject/node_modules/chartjs-node/node_modules/bluebird/js/release/promise.js:614:10)
    at Promise._settlePromises (/Users/theBigProject/node_modules/chartjs-node/node_modules/bluebird/js/release/promise.js:693:18)
    at Promise._fulfill (/Users/theBigProject/node_modules/chartjs-node/node_modules/bluebird/js/release/promise.js:638:18)
    at Object.done (/Users/theBigProject/node_modules/chartjs-node/node_modules/bluebird/js/release/nodeback.js:42:21)
    at process.nextTick (/Users/theBigProject/node_modules/jsdom/lib/jsdom.js:320:18)
    at _combinedTickCallback (internal/process/next_tick.js:73:7)
    at process._tickCallback (internal/process/next_tick.js:104:9)

This is my sample code:

const ChartjsNode = require('chartjs-node');
let chartNode = new ChartjsNode(600, 600);
let chartJsOptions = {
        "type": "pie",
        "data": {
            "labels": ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
            "datasets": [{
                "label": "# of Votes",
                "data": [12, 19, 3, 5, 2, 3],
                "backgroundColor": [
                    "rgba(255, 99, 132, 0.2)",
                    "rgba(54, 162, 235, 0.2)",
                    "rgba(255, 206, 86, 0.2)",
                    "rgba(75, 192, 192, 0.2)",
                    "rgba(153, 102, 255, 0.2)",
                    "rgba(255, 159, 64, 0.2)"
                ],
                "borderColor": [
                    "rgba(255,99,132,1)",
                    "rgba(54, 162, 235, 1)",
                    "rgba(255, 206, 86, 1)",
                    "rgba(75, 192, 192, 1)",
                    "rgba(153, 102, 255, 1)",
                    "rgba(255, 159, 64, 1)"
                ],
                "borderWidth": 1
            }]
        },
        "options": {
            "scales": {
                "yAxes": [{
                    "ticks": {
                        "beginAtZero": true
                    }
                }]
            }
        }
    };

    return chartNode.drawChart(chartJsOptions)
        .then(() => {
            return chartNode.getImageBuffer('image/png');
        })
        .then(buffer => {
            Array.isArray(buffer) // => true
            // as a stream
            return chartNode.getImageStream('image/png');
        })
        .then(streamResult => {
            // using the length property you can do things like
            // directly upload the image to s3 by using the
            // stream and length properties
            streamResult.stream // => Stream object
            streamResult.length // => Integer length of stream
            // write to a file
            return chartNode.writeImageToFile('image/png', './testimage.png');
        })
        .then(() => {
            chartNode.destroy();
        });

Hi, I have a quick workaround to get past this issue. Just add the "xAxes" property as an empty array [] in the options -> scales setting and it will work. I have updated your code.


const ChartjsNode = require('chartjs-node');
let chartNode = new ChartjsNode(600, 600);
let chartJsOptions = {
        "type": "pie",
        "data": {
            "labels": ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
            "datasets": [{
                "label": "# of Votes",
                "data": [12, 19, 3, 5, 2, 3],
                "backgroundColor": [
                    "rgba(255, 99, 132, 0.2)",
                    "rgba(54, 162, 235, 0.2)",
                    "rgba(255, 206, 86, 0.2)",
                    "rgba(75, 192, 192, 0.2)",
                    "rgba(153, 102, 255, 0.2)",
                    "rgba(255, 159, 64, 0.2)"
                ],
                "borderColor": [
                    "rgba(255,99,132,1)",
                    "rgba(54, 162, 235, 1)",
                    "rgba(255, 206, 86, 1)",
                    "rgba(75, 192, 192, 1)",
                    "rgba(153, 102, 255, 1)",
                    "rgba(255, 159, 64, 1)"
                ],
                "borderWidth": 1
            }]
        },
        "options": {
            "scales": {
                "yAxes": [{
                    "ticks": {
                        "beginAtZero": true
                    }
                }],
                "xAxes":[]
            }
        }
    };

    return chartNode.drawChart(chartJsOptions)
        .then(() => {
            return chartNode.getImageBuffer('image/png');
        })
        .then(buffer => {
            Array.isArray(buffer) // => true
            // as a stream
            return chartNode.getImageStream('image/png');
        })
        .then(streamResult => {
            // using the length property you can do things like
            // directly upload the image to s3 by using the
            // stream and length properties
            streamResult.stream // => Stream object
            streamResult.length // => Integer length of stream
            // write to a file
            return chartNode.writeImageToFile('image/png', './testimage.png');
        })
        .then(() => {
            chartNode.destroy();
        });

@akhilrex oh yeah, nice! Thanks :)

Closing this one out since the Exception is originating from chart.js due to the chart.js options.

I don't know where Exception is arising from. But its just badly written cases.

if (configuration.options.plugins) { Chartjs.pluginService.register(configuration.options.plugins); }

Could be easily written as:
if (configuration.options && configuration.options.plugins) { Chartjs.pluginService.register(configuration.options.plugins); }

to prevent such exceptions.
This was just one example, many exceptions are thrown if options aren't specified in the chartJsOptions object.