How to get months to show correctly in a morris.js chart?
Asked Answered
E

1

7

I am having an issue getting months to show correctly in a morris.js chart.

<script>

var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

Morris.Line({
  element: 'morris-line-chart',
  data: [
          { m: '01', a: 0, b: 270 },
          { m: '02', a: 54, b: 256 },
          { m: '03', a: 243, b: 334 },
          { m: '04', a: 206, b: 282 },
          { m: '05', a: 161, b: 58 },
          { m: '06', a: 187, b: 0 },
          { m: '07', a: 210, b: 0 },
          { m: '08', a: 204, b: 0 },
          { m: '09', a: 224, b: 0 },
          { m: '10', a: 301, b: 0 },
          { m: '11', a: 262, b: 0 },
          { m: '12', a: 199, b: 0 },
        ],
  xkey: 'm',
  ykeys: ['a', 'b'],
  labels: ['2014', '2015'],
  xLabelFormat: function (x) { return months[x.getMonth()]; }
});
</script>

but all months on the chart show as 'Jan' ...

Erl answered 8/5, 2015 at 17:53 Comment(6)
According to the documentation xLabelFormat: accepts Date objects, where you are providing strings.Daisy
So it isn't possible?Erl
Instead of using strings, use date objects and return them as month strings .Daisy
The 01, 02 is output from SQL result. It must be 01, 02 etc. so the output is in order ... If I output as January, February then it won't be in order ...Erl
the x in xLabelFormat: is intended to be a Date object, not a string. Currently, months is a string array. Just make those month strings Date objects instead. this has nothing to do with dataDaisy
Sorry I don't understand?Erl
D
16

If you look at the documentation, the required xkey option is defined like this:

A string containing the name of the attribute that contains date (X) values. Timestamps are accepted in the form of millisecond timestamps (as returned by Date.getTime() or as strings in the following formats:

  • 2012
  • 2012 Q1
  • 2012 W1
  • 2012-02
  • 2012-02-24
  • 2012-02-24 15:00
  • 2012-02-24 15:00:00
  • 2012-02-24 15:00:00.000

Currently, in your data, you are only supplying an int representing the month (ie 01, 02, 03, etc.)

So if you change your month data to be a valid timestamp string, according to the documents, you should then have a valid method for mapping the index of the returned "month" value to your months label array...

Example:

var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

Morris.Line({
  element: 'morris-line-chart',
  data: [{
    m: '2015-01', // <-- valid timestamp strings
    a: 0,
    b: 270
  }, {
    m: '2015-02',
    a: 54,
    b: 256
  }, {
    m: '2015-03',
    a: 243,
    b: 334
  }, {
    m: '2015-04',
    a: 206,
    b: 282
  }, {
    m: '2015-05',
    a: 161,
    b: 58
  }, {
    m: '2015-06',
    a: 187,
    b: 0
  }, {
    m: '2015-07',
    a: 210,
    b: 0
  }, {
    m: '2015-08',
    a: 204,
    b: 0
  }, {
    m: '2015-09',
    a: 224,
    b: 0
  }, {
    m: '2015-10',
    a: 301,
    b: 0
  }, {
    m: '2015-11',
    a: 262,
    b: 0
  }, {
    m: '2015-12',
    a: 199,
    b: 0
  }, ],
  xkey: 'm',
  ykeys: ['a', 'b'],
  labels: ['2014', '2015'],
  xLabelFormat: function(x) { // <--- x.getMonth() returns valid index
    var month = months[x.getMonth()];
    return month;
  },
  dateFormat: function(x) {
    var month = months[new Date(x).getMonth()];
    return month;
  },
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css" rel="stylesheet" />
<script src="http://cdn.oesmith.co.uk/morris-0.5.0.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>

<div id="morris-line-chart" style="height: 250px;"></div>

Edit

The above example can be adjusted for bar charts by including morris version 0.5.1 (instead of 0.5.0 - according to the github page about this issue - I have not tested this in other versions) and slightly changing the xLabelFormat option (the x in function(x){...} apparently is a different object with bar charts vs line):

Bar Chart Example:

// months array and data are left the same
// only change is that the labelFormat option is removed
// and, x in xLabelFormat is a different object with Bar charts vs Line

// [inspect console to see the object]

var months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];

Morris.Bar({
    element: 'morris-bar-chart',
    data: [{
        m: '2015-01',
        a: 0,
        b: 270
    }, {
        m: '2015-02',
        a: 54,
        b: 256
    }, {
        m: '2015-03',
        a: 243,
        b: 334
    }, {
        m: '2015-04',
        a: 206,
        b: 282
    }, {
        m: '2015-05',
        a: 161,
        b: 58
    }, {
        m: '2015-06',
        a: 187,
        b: 0
    }, {
        m: '2015-07',
        a: 210,
        b: 0
    }, {
        m: '2015-08',
        a: 204,
        b: 0
    }, {
        m: '2015-09',
        a: 224,
        b: 0
    }, {
        m: '2015-10',
        a: 301,
        b: 0
    }, {
        m: '2015-11',
        a: 262,
        b: 0
    }, {
        m: '2015-12',
        a: 199,
        b: 0
    }, ],
    xkey: 'm',
    ykeys: ['a', 'b'],
    labels: ['2014', '2015'],
    xLabelFormat: function (x) { // <-- changed
        console.log("this is the new object:" + x);
        var month = months[x.x];
        return month;
    },
});
<link href="http://cdn.oesmith.co.uk/morris-0.4.3.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://cdn.oesmith.co.uk/morris-0.5.1.min.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>


<div id="morris-bar-chart" style="height: 250px;"></div>
Daisy answered 12/5, 2015 at 15:2 Comment(6)
Thanks, works perfectly. Is there a reason that it wouldn't work on a bar chart? I get Uncaught TypeError: x.getMonth is not a function.Erl
According to this GitHub page xLabelFormat is only supported in morris-0.5.1 (the snippet is 0.5.0). I just quickly tested it and it works. I'll update the answer.Daisy
I still can't get this to work. I am trying to have a line chart and bar chart on both pages using xLabelFormat, it works on the line chart but when it gets to the bar chart it throws Uncaught TypeError: x.getMonth is not a functionMorris.Bar.xLabelFormat @ (index):421(anonymous function) @ morris.min.js:6b.Grid.d.setData @ morris.min.js:6d @ morris.min.js:6d @ morris.min.js:6d @ morris.min.js:6(anonymous function) @ (index):400. I have updated as suggested.Erl
@Erl - the x in xLabelFormat : function(x) { //... //} is a different object in Line Chart vs Bar Chart. months[x.getMonth()] won't work in Bar because x is not a date like it is in Line. If you notice in the Bar example in this answer, the mapping works like this: months[x.x]...Daisy
@Daisy I have an issue regarding morris. My month are coming in the form of numbers from database like (1,2,3..). Thing is that for certain month values e.g 4 and 5 there are no values in my table. Now I want to display name of month rather than its number. I used your solution for this question, it worked. But now it includes those months also which does not actually have values. e.g if 4 and 5 are missing then it shows april and may on the graph. How I can get rid of thisMeyers
@AmitKaushal - This should be a separate question, not a comment.Daisy

© 2022 - 2024 — McMap. All rights reserved.