1

So I'm trying to build a pie chart using chartjs in meteor.

I'm pretty sure the problem is that the order of precedence is talking over here.

I need the object in this order

{
    value: 900.65,
    color:"#red",
    highlight: "#FF5A5E",
    label: "income"
}

but i get it in this order

{
    color: "#red"
    highlight: "#FF5A5E"
    label: "income"
    value: 900.65
}

This is my loop

    function drawExpPie(){
  data = [];
  var Task = Tasks.find({},{fields:{value:1,text:1}}).fetch();
  for(var i = 0; i < Task.length; i++)  {
    var newdataset = {
      label:Task[i].text,
      highlight: "#FCA456",
      color: "red",
      value:Task[i].value,
      };
    data.push(newdataset);
  }
  console.log(data);
  var context = document.getElementById('myExpChart').getContext('2d');
  var myPieChart = new Chart(context).Pie(data);
}

Template.exp.helpers({
  exp: function() {return Session.get("exp");}
});

Template.exp.rendered = function(){
  drawExpPie();
};

Any help is appreciated. Thanks

techn3rd
  • 11
  • 3
  • 1
    What is the problem exactly? Any error that leads you to thinking about precedence? – jjczopek Sep 09 '15 at 23:45
  • 1
    objects in javascript do not have any guaranteed order. Also your two objects have different field values. Is there an array you are talking about but not showing? I'm very confused. Also your for loop couldn't produce the first object (different values). – Christian Fritz Sep 10 '15 at 00:04
  • Sorry for the confusion. I'll add a little more code – techn3rd Sep 10 '15 at 00:12
  • 2
    Property order doesn't matter. What's the actual problem that you're trying to solve? – ffxsam Sep 10 '15 at 00:18
  • My problem is that my pie chart won't draw unless I put the array inside the for loop. The problem then is that if I do that I only end up with one object. because the array is reset each iteration – techn3rd Sep 10 '15 at 01:01
  • @techn3rd There is no way to get an object whose property is sorted as you want, if you use something like `for in` to traverse an object, you would find that **different browser has different implementations**. – Total Shaw Sep 10 '15 at 01:43
  • 1
    If your `data` variable is actually an array, then `data.push()` will *not* "reset" the array. It will append to the end of the array each time. There has to be something you're misunderstanding, or something you're not showing us. Also I'll reiterate the other comments about the order of properties within an object: it just doesn't matter. If you write code where the order *does* matter, such as a `for`-`in` loop, you're most likely doing it wrong. And certainly code like chart.js will not rely on the order of properties within an object. – Michael Geary Sep 10 '15 at 01:43
  • It does matter because chartjs requires the object to be in the required format. I have added more code. hopefully that helps. – techn3rd Sep 10 '15 at 01:49
  • @TotalShaw and others: Actually, all modern browsers *do* preserve the order in which you add properties to an object in the typical case where you have non-numeric keys, and in fact this behavior has been codified in the latest JavaScript standard. But of course a library like chart.js is very unlikely to rely in this, as it would access properties by name like `obj.color` etc. – Michael Geary Sep 10 '15 at 01:52
  • I refuse to believe that chart.js relies on the order of properties within an object. No professional JavaScript library behaves that way. Of course it relies on the specific property *names*, but not their order - that would be madness. – Michael Geary Sep 10 '15 at 01:55
  • According to chart.js documentation, a Pie chart requires a `color` and `value` property for each object in the array passed in. The order of those properties doesn't matter - you target `color` and `value` for the given object in the array. The example shows it in that order, but the actual order is irrelevant. The comments here are correct. http://www.chartjs.org/docs/#doughnut-pie-chart – mc01 Sep 10 '15 at 01:55
  • That might be true, if the array is in the loop it will draw but it will only have one object. if I put it where it is in my code sample i can console.log every object in data but it won't draw – techn3rd Sep 10 '15 at 01:57
  • Your loop looks fine. `data` should end up with the same number of elements as `Task`. Perhaps `Task` only has one element: what is the value of `Task.length`? Also, as a suggestion you might try `console.log(JSON.stringify(data,null,4))` to get a more clear picture of what's in `data`. – Michael Geary Sep 10 '15 at 02:02
  • You mean if you declare `var data =[];` inside the `for` loop? Yes, then it's scoped to the loop, gets reset each time & disappears. If it doesn't draw w/the array *outside* the loop (it should) there's some other error. Regardless, the order of object properties isn't the problem. Anything in your console? Ignoring the pie chart for the moment, what is displayed when you `console.log(data)`? – mc01 Sep 10 '15 at 02:02
  • in my code sample where the console.log is i get every object in the array. – techn3rd Sep 10 '15 at 02:05
  • 1
    BTW the code inadvertently makes `data` a global variable. This could be messing things up, depending on what else the code does. It should be `var data = [];`. – Michael Geary Sep 10 '15 at 02:05
  • I've change to var.. this is what i get in the console [ Object color: "red" highlight: "#FCA456" label: "Living" value: 350.56 __proto__: Object __defineGetter__: function __defineGetter__() { __defineSetter__: function __defineSetter__() { __lookupGetter__: function __lookupGetter__() { __lookupSetter__: function __lookupSetter__() { constructor: function Object() { hasOwnProperty: function hasOwnProperty() { isPrototypeOf: function isPrototypeOf() { propertyIsEnumerable: function propertyIsEnumerable() { toLocaleString: function toLocaleString() { toString: .. valueOf: function valueOf() { – techn3rd Sep 10 '15 at 02:07
  • that's for each object. – techn3rd Sep 10 '15 at 02:07
  • If it helps at all I get this in the c9 console. Exception from sub pie id 8QbwtyGFpnbdmzmJw Error: Publish function returned an array of non-Cursors I20150910-02:20:32.393(0)? at [object Object]._.extend._runHandler (packages/ddp/livedata_server.js:997:1) .... – techn3rd Sep 10 '15 at 02:23
  • Any `value` undefined? Ok, so if it drew the "last" pie section fine inside the loop but throws this error otherwise, one of the previous `value`s in data may be undefined or not a number. Beyond that, not sure... – mc01 Sep 10 '15 at 02:24
  • The only practical thing for you to do at this point is create a [fiddle](http://jsfiddle.net/) that demonstrates the problem. You don't need Meteor, you can just provide canned test data. Otherwise we're all just guessing. In fact, in the process of creating a fiddle you may well discover what the problem is yourself. Or if not, someone will be able to see the problem easily once they can look at running code. – Michael Geary Sep 10 '15 at 02:32
  • 1
    possible duplicate of [Does JavaScript Guarantee Object Property Order?](http://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order) – Jan Sep 10 '15 at 02:58
  • @Michael Geary I believe it would be pointless making a fiddle as it doesn't support meteor. – techn3rd Sep 10 '15 at 03:39
  • You don't need Meteor to make a fiddle. Call `JSON.stringify(Task)` after you assign the `Task` variable in your Meteor code, and use the resulting JSON object as the source data for your fiddle. – Michael Geary Sep 10 '15 at 04:05
  • Thanks for the tip @Michael Geary. – techn3rd Sep 10 '15 at 04:11

2 Answers2

0

This fixed it...

    for(var i = 0; i < Task.length; i++)  {
    data.push({
      label: Task[i].text,
      highlight: "#FF5A5E",
      color:"#F7464A",
      value: Number(Task[i].value)
      });
  }

Keynote : value: Number(Task[i].value) would likely work as well.

techn3rd
  • 11
  • 3
0

Change value:Task[i].value to

 value:Task[i].value || 0,
potatopeelings
  • 40,709
  • 7
  • 95
  • 119