2

I'm using D3js with Mongodb and AnguarlJS to display my data. All is good that it works until when I give my JSON array a name. Then angular starts complaining about stuff and I'm not sure why.

this is the original json array that works with this original code

[

  {
    "defaultCategory":"Happy",
    "timesUsed":2704659
  },
  {
    "defaultCategory":"Sad",
    "timesUsed":4499890
  },
  {
    "defaultCategory":"Laughter",
    "timesUsed":2159981
  },
  {
    "defaultCategory":"Smirk",
    "timesUsed":3853788
  },
  {
    "defaultCategory":"Flirty",
    "timesUsed":14106543
  }
]


d3.json("data.json", function(error, data) {
        data.forEach(function(d) {
           d.timesUsed =+ d.timesUsed;
    }); 

but when i change the json to this format, it breaks

{
  "mymood":[

  {
    "defaultCategory":"Happy",
    "timesUsed":2704659
  },
  {
    "defaultCategory":"Sad",
    "timesUsed":4499890
  },
  {
    "defaultCategory":"Laughter",
    "timesUsed":2159981
  },
  {
    "defaultCategory":"Smirk",
    "timesUsed":3853788
  },
  {
    "defaultCategory":"Flirty",
    "timesUsed":14106543
  }
]

}


 d3.json("data.json", function(error, data) {
        data.mymood.forEach(function(d) {
           d.timesUsed =+ d.timesUsed;
    }); 

In the chrome console the error is happening at the line data.mymood.foreach line, but i dont understand why because its exactly returning the same json as if there was no name like this

[object, object, object,object,object]

and the parameter d in the function also returns the same object within the array

edit

Error:

Uncaught TypeError: undefined is not a function

console.log(data) -> Object {mymood: Array[5]}

console.log(data.mymood) -> [Object, Object, Object, Object, Object]

gist for those who are interested in the full code

https://gist.github.com/gwong89/e3a29b64d94ad20256bb

Apprentice Programmer
  • 1,485
  • 4
  • 26
  • 39

3 Answers3

1

Like Oscar had pointed out, the forEach loop works fine. However, after look closely at your gist, if you try to use the mymood key, make sure you also change line 55 where you were using

var g = svg.selectAll('g')
            .data(pie(data))

to

var g = svg.selectAll('g')
            .data(pie(data.mymood))

Also on line 76 where you had

var total = d3.sum(data.map(function(d) { 

to

var total = d3.sum(data.mymood.map(function(d) { 

I grabbed your project repo and tried these out on my local environment, and I can render the pie chart and popup without seeing any errors.

dotcomXY
  • 1,586
  • 1
  • 15
  • 18
0

Your code seems to be working fine (from what I've tested). I will suggest to try debugging your code or if you feel more comfortable try doing many console.log(...) as possible and keep checking your browser console from the beginning (I have nothing else to say). Try to also use Developer Tools from Chrome which is a better option.

I've tried to replicate your context by using d3.js library and uploaded a json file with your data to my Dropbox just to be able to perform an ajax request and everything is fine again (also new JSON structure is valid). Here's what I did, probably could help you to learn something new (see below).

Possible hints/suggestions to fix your issue:

According to the question title, it seems that data.mymood is undefined so you are not able to do a forEach of something that doesn't exist. Try validating things and avoid null pointers (see example).

JSON structures are valid so that's not the problem.

Syntax seems to be valid from what I've tested.

Check if there's a conflict between libraries, try to do some research about using all the libraries needed together (not sure if this is your situation but could happen).

Check your browser console and do some debugging as the first paragraph says.

Check if your request is not timing out or something else is happening, check the Network tab or log your requests in browser console using Developer Tools from Chrome (just saying).

Live Demo: http://jsfiddle.net/29f6n8L7/

d3.json('https://dl.dropboxusercontent.com/u/15208254/stackoverflow/data.json', function(data) {
    
    // Some ways to avoid null pointers
    var obj = (data || {}), // If 'data' is null, initialize as an Object
        moods = (obj.mymood || []),  // If 'obj.mymood' is null, initialize as an Array
        time = 0, 
        mood;
        
    // Same way to get 'mymood' from the object
    console.log('Your obj.mymood contains: %o', obj.mymood);
    console.log('Your obj["mymood"] contains: %o', obj['mymood']);

    /**
     * I will suggest to use a traditional loop instead of 'forEach'.
     * Please read: http://stackoverflow.com/a/9329476/1178686
     * for a better explanation    
     */
    for (var i = 0; i < moods.length; ++i) {
        mood = moods[i];
        if (mood) {
            time += mood.timesUsed;
        }
    }
    
    // Output
    console.log('Sum of timesUsed is: %s', time);
});
Community
  • 1
  • 1
Oscar Jara
  • 14,129
  • 10
  • 62
  • 94
  • hey oscar, great post and i appreciate it. I fiddled around with your suggestion, the for loop works but it will take a great deal of pain to rename all my variables and hack something to work. Also, i checked the chrome console again and realized was coming from the d3.js library itself. – Apprentice Programmer Feb 12 '15 at 08:46
-3

Arrays have a built in for each in es5, objects do not.

Bob Barker
  • 236
  • 1
  • 9