Marcus Gladir
Marcus Gladir

Reputation: 423

morris.js setData causes "Uncaught TypeError: Cannot read property 'x' of undefined"

I am trying to draw a bar graph that gets updated when a dropdown selection changes.

The following code is included in my html doc, and the leaveStayGraph function is called onChange of dropdown. Every time after the first time leaveStayGraph is called, I get the following error:

Uncaught TypeError: Cannot read property 'x' of undefined

Before subsequent calls (when setData is called), leaveStayData looks perfectly fine (in fact it looks just about the same as it did on the first call, which worked).

var leaveStayChart = null;
function leaveStayGraph(display_data, date) {

    /* Do stuff to get data */

    // Draw Chart
    var leaveStayData = {
        element: 'leave_stay_pie_chart',
        data: [{
            label: "Stayed",
            value: count
        }, {
            label: "Left",
            value: total - count
        }],
        xkey: 'label',
        ykeys: ['value'],
        labels: ['Count'],
        hideHover: 'auto'
    };

    if (leaveStayChart == null) {
        // FIRST CALL
        leaveStayChart = Morris.Bar(leaveStayData);
    }
    else {
        // SUBSEQUENT CALLS
        leaveStayChart.setData(leaveStayData);
    }
}

My end goal is to update the graph upon changing the selection of the dropdown, but every time setData is called, I get this error and nothing displays. Is something happening that I can change.

UPDATE

Just to clarify, the basic idea is something like this (half-taken from the example from morris.js). When the button is pressed, the chart updates.

var x = Morris.Bar({
  element: 'bar-example',
  data: [
    { y: '2006', a: 100, b: 90 },
    { y: '2007', a: 75,  b: 65 },
    { y: '2008', a: 50,  b: 40 },
    { y: '2009', a: 75,  b: 65 },
    { y: '2010', a: 50,  b: 40 },
    { y: '2011', a: 75,  b: 65 },
    { y: '2012', a: 100, b: 90 }
  ],
  xkey: 'y',
  ykeys: ['a', 'b'],
  labels: ['Series A', 'Series B']
});

document.write("<button onClick='update()'>Test</button>");

function update() {
  x.setData({
  element: 'bar-example',
  data: [
    { y: '2006', a: 100, b: 1 },
    { y: '2007', a: 75,  b: 65 },
    { y: '2008', a: 46,  b: 40 },
    { y: '2009', a: 43,  b: 41 },
    { y: '2010', a: 50,  b: 40 },
    { y: '2011', a: 3,  b: 2 },
    { y: '2012', a: 30, b: 90 }
  ],
  xkey: 'y',
  ykeys: ['a', 'b'],
  labels: ['Series A', 'Series B']
});
}

Upvotes: 2

Views: 4343

Answers (2)

JoeyZero
JoeyZero

Reputation: 575

So you are on the right track, you just need to pass in the JSON data to setData instead of the entire graph object. So this would be my revised version of your code:

var leaveStayChart = null;
function leaveStayGraph(display_data, date) {

    /* Do stuff to get data */
    var graphData = [{
            label: "Stayed",
            value: count
        }, {
            label: "Left",
            value: total - count
        }];

    if (leaveStayChart == null) {
        // FIRST CALL
        leaveStayChart = Morris.Bar({
            element: 'leave_stay_pie_chart',
            data: graphData,
            xkey: 'label',
            ykeys: ['value'],
            labels: ['Count'],
            hideHover: 'auto'
        });
    }
    else {
        // SUBSEQUENT CALLS
        leaveStayChart.setData(graphData);
    }
}

Upvotes: 2

Marcus Gladir
Marcus Gladir

Reputation: 423

The issue is that setData doesn't take in the same type of object that is passed in to Morris.Bar(data). The object passed into the setData function is the value under data in the original object.

This would be the revised sample code:

var x = Morris.Bar({
  element: 'bar-example',
  data: [
    { y: '2006', a: 100, b: 90 },
    { y: '2007', a: 75,  b: 65 },
    { y: '2008', a: 50,  b: 40 },
    { y: '2009', a: 75,  b: 65 },
    { y: '2010', a: 50,  b: 40 },
    { y: '2011', a: 75,  b: 65 },
    { y: '2012', a: 100, b: 90 }
  ],
  xkey: 'y',
  ykeys: ['a', 'b'],
  labels: ['Series A', 'Series B']
});

document.write("<button onClick='update()'>Test</button>");

function update() {
  x.setData([
    { y: '2006', a: 100, b: 1 },
    { y: '2007', a: 75,  b: 65 },
    { y: '2008', a: 46,  b: 40 },
    { y: '2009', a: 43,  b: 41 },
    { y: '2010', a: 50,  b: 40 },
    { y: '2011', a: 3,  b: 2 },
    { y: '2012', a: 30, b: 90 }
  ]);
}

Upvotes: 0

Related Questions