D3: Visualize Data with a Bar Chart - Important Tips

While completing the first Data Visualization project - “Visualize Data with a Bar Chart” - I initially had a lot of issues getting the tests to pass, even though I had fulfilled all the user stories properly. I found that not everything was explained in FCC’s curriculum. So, I just wanted to share a couple of tips/pointers for anyone out there who might be pulling their hair out trying to get their tests to pass.

  1. Don’t use scaleLinear() for the x-axis. While it’s the only scale that the FCC curriculum teaches, and you can get it to functionally work by formatting the tick marks and labels (which I spent time doing), unfortunately, the tests wont pass if you try it. You want to use scaleTime(). Here is a short guide: D3.js scaleTime() Function - GeeksforGeeks But the gist is that the domain needs an array of two Date objects (the earliest date in your dataset and latest date in your dataset). I don’t recall if the JavaScript DS&A covers date objects (I don’t think it does), but you can Google “javascript date constructor” to find a tutorial.

  2. Ignore the FCC “Add a Tooltip to a D3 Element” challenge - this method will work fine, but the tests will fail. Instead you need to create a tooltip like a modal. I don’t think FCC covers modals at all, but there are plenty of tutorials out there. In short, you want to create a div element that appears when the bars are hovered over. And I just passed all the info the modal needs via data attributes.

  3. You can’t use standard JavaScript event handlers to make the tooltip modal appear/disappear or the tests will fail. You need to use D3’s built-in .on() method. Again, this isn’t explained at all in the FCC curriculum, but it’s pretty simple. It just takes two parameters - the event and a function - the same as the standard JavaScript .addEventListener() method.

I hope that helps anyone. Here is a link to my completed Bar Chart project, if anyone is still confused and wants to take a look: https://codepen.io/andytburke/full/OJEyJGd

Your post is a good warning that these projects are hard and are a step up in difficulty from the projects for the earlier parts of the curriculum. They require a lot of research in order to extend what you know to create new visualizations.

This is typical. The exercises are introductory; there’s no way everything in D3 could be covered in a few dozen exercises. That’s the point of the projects: take the introductory knowledge and expand it with research.

You really shouldn’t use linear anything for a bar chart since you are representing chunks of time. A time scale or a band scale makes much more sense. D3 uses ‘linear’
where I really think they mean continuous (as opposed to discrete; bar graphs are discrete). The seventh content test sets this requirement fairly clearly as it’s checking for dates attached to bars, using the data in the data set. Since the bars have to match the tooltip and the axis, you really are stuck with scaleTime().

Your provided link has a problem though: it’s outdated and uses D3v4 (it’s D3v7 now and backwards compatibility breaks on major versions). While it doesn’t matter in this case, D3 links have a high rate of bit rot and the only safe documentation is from D3’s github, even if you consult it after using another source.

This is well documented in the forums. The test is explicit in the requirements of attributes for the tooltip, which can’t be done with the SVG title element. I also figured this out the hard way, although I can’t remember if it’s the lack of attributes on title or the transition times that prevent it from working because I really jumped through some hoops trying to get it to work even though doing it with a div is so much easier. The lesson text does say title is only one way to create a tooltip; it just doesn’t mention the others. It could be clearer, though, as this trips a lot of people.

Those are standard events. The whole point of D3 is to do stuff like d3.select(...).on(...) and let it handle finding the DOM elements and mapping them to the appropriate data. D3 is like React; it stands between you and the DOM to make life easier, but they both still use plain old javascript behind the scenes. Things often go wrong if you try to manually manipulate the DOM when something like D3 or React is trying to manipulate it too.

I think what bothers me about it, from a learning perspective, is that you’re shown a way to do it - particularly with the tooltip issue - but the project expects you to do it a different way, without making it clear that you’re even supposed to be looking for another way to do it. I could understand it more if the point was “we want you to learn how to do your own research and learn to read docs,” but that doesn’t actually get communicated or taught at all. So it reads to me more like a “oops, we forgot to make a lesson about scaleTime!” Just my personal opinion, sorry.

I was able to fulfill this requirement with scaleLinear() because you can set the ticks however you want (I did it by mapping the dates to an array, then using a modulo to set the frequency they display), though scaleTime() turned out to much easier.

This seemed to work with the title elements, at least both the id and data-date attributes were there on the title when I checked the developer tools. So I’m really not sure why this didn’t work.

Perhaps, though I didn’t see any issues. Honestly, it seemed way easier to just add an event listener the body and run the visible/hidden functions for the tooltip when it triggered a rect element. But I’m very new to D3 obviously.

Also - I was able to complete the Scatterplot Graph (the second project) much quicker knowing about using a div for the tooltip and the scaleTime method!

I wanted to add a couple more notes, in case anyone finds this in the future:

The second project (scatterplot graph) and the third project(heat map) aren’t too difficult to complete once you’ve complete the first project. In fact, I was able to re-use a lot of my code from the first project. So as long as you feel okay about the first project, you shouldn’t have too much trouble with the other two.

The fourth project, The Choropleth Map, is a different story. The big challenge here is rendering the map onto the svg. You’ll have to learn how to fetch data using two separate APIs simultaneously. I have no idea how to do this with using XMLHttpRequest, but if you use .fetch(), I’d say do some quick research into Promise.all. That’s the method I used, and it was pretty simple, but it might be even better to learn how to use async/await. FCC doesn’t teach this, but it’s probably the more common approach these days.

Also, IMPORTANT, you need to use the TopoJSON library to render the map. It’s amazing to me that the project doesn’t mention this at all, but it’s how they’ve encoded their geography data. And, honestly, the documentation is very technical and hard to understand, so I’m just going to show you how to do it. This is the explanation I wish I didn’t have to dig for:

  map.selectAll("path")
     .data(topojson.feature(mapData, mapData.objects.counties).features)
     .enter()
     .append("path")
     .attr("d", d3.geoPath())

To explain stuff that the FCC course didn’t cover: First, “path” is an element that can be turned into a curve or arc, which is good for drawing complex things like geography. I can’t fully explain how the “feature” method works, but it’s how you’re going to convert this data into something that D3 can use. It takes two arguments, the first is the entire json object you are getting from the FCC map data API, and the second is the .counties data that is nested within that map data json. You can do the same with .states if you want to draw the borders for each U.S. state. This method creates an object, and you need to specifically grab .features from the object. Finally, when you add the “d” attribute to your path elements, you have to pass it into D3’s .geoPath() method. That’s how all this stuff gets drawn properly on your SVG.

Once you get your map rendered, completing the project is straight forward. You have to add a tooltip and a legend, which is all stuff you’d have done in the previous projects. Hope that helps!