fCC D3 Bar chart 9th/10th tests unexplainably failing

Two that are failing:

  1. Each bar element’s height should accurately represent the data’s corresponding GDP

and

  1. The data-date attribute and its corresponding bar element should align with the corresponding value on the x-axis.

This other fCC forum post recommends using d3.scaleTime() instead of d3.scaleLinear() but that didn’t fix my issue. Also, I wrote a convertDate() helper which takes in a string and returns a Date() object already so that the xScale works properly.

I get the data-date issue when I pass in d[0] and convertDate(d[0]) so not sure what the issue is there.

For #9, here is how I set the height of the bars:

    const yScale = d3.scaleLinear()
    .domain([0
             d3.max(gdp, (d) => d[1])])
    .range([h-padding, padding])

Perhaps 0 should be d3.min(gdp, (d) => d[1]) instead? This forum post recommended scaling from minimum to maximum. That also didn’t fix it. Specifically in the code I set my bar height like this:

      .attr("y", (d,i) => (yScale(d[1])) + "px")
       .attr("height", (d, i) => {
         return h-padding + "px";
       })

Here’s my Codepen—thanks in advance!

PS—if anyone on fCC staff is reading this, the way tooltips are taught in the curriculum does not pass the tests. This post has a code snippet I (properly attributed and) used for how it actually works, but without prior knowledge of D3/looking on the forum I wouldn’t have been able to solve it.

Hi @lucasgelfond!

The reason for this is the way you set height. Notice that height will always be the same value, which is 195.

const h = 200;
const padding = 5;

// ...

.attr("height", (d, i) => {
  return h-padding + "px";
})

Because of that your bars look like this:

You probably want to use yScale for the height of the bars :wink:

Here there is definitely something wrong with the tick values. The axis itself is not visible but when you inspect the bar chart you’ll find:

x-axis

I think the problem is that you’re passing dates to scaleLinear.

d3 docs:

If domain is specified, sets the scale’s domain to the specified array of numbers. The array must contain two or more elements. If the elements in the given array are not numbers, they will be coerced to numbers.

This basically mean that scaleLinear will try to interpret any string to a number, probably that’s why there are this weird numbers in the picture above.

If you want to use dates, use scaleTime, if you want to use numbers use scaleLinear.

Good luck :slight_smile:

1 Like

Thank you so much for your kind + thorough + quick response!

scaleTime() with the Date objects fixed that issue!

The height thing makes sense,

I changed yScale to reflect lower GDP corresponding with lower height values and higher GDP corresponding with higher height values:

    const yScale = d3.scaleLinear()
    .domain([0, 
             d3.max(gdp, (d) => d[1])])
    .range([padding, h-padding])
    

And here’s how I’m setting height now:

       .attr("height", (d, i) => {
         return yScale(d[1]) + "px";
       })

If I don’t use y to position, they show up upside down!

Screen Shot 2021-01-20 at 1.36.09 AM

This makes sense because of the way d3 publishes with lower values on top and higher values going lower. To remedy this, I set y like this, after some tinkering:

.attr("y", (d,i) => (h-padding-yScale(d[1]) + "px"))

This fixed it! This became my graph:
Screen Shot 2021-01-20 at 1.37.44 AM

That, however, failed test 9 (" Each bar element’s height should accurately represent the data’s corresponding GDP") and, for the first time, test 11 (" The data-gdp attribute and its corresponding bar element should align with the corresponding value on the y-axis.")

When I try and swap yScale back to what it was, this also doesn’t solve the problem:
Screen Shot 2021-01-20 at 1.41.58 AM

This is the result of swapping the last .range([padding, h-padding]) that I changed bck to .range([h-padding, padding])

I can tell I’m super close but I have no idea what to try/google/how else to troubleshoot! Would love any other thoughts—thank you so much again for being so helpful + generous with your time!

Too find the problem we actually should take a one step back and try to solve the missing axes.

At the moment we can’t see any ticks so it’s hard to say why they are wrong.

To fix see the axis you could use what’s called The Margin Convention. In a nutshell it’s a convenient way of making some space for the axes.

The best guy out there that explain all kind of d3 related stuff is in my opinion Curran Kelleher, and here you can find him explaining The Margin Convention:

I’m confused about how we don’t see ticks! I see them in the image of the graph—what do you mean? Also it is passing the test for ticks so I’m assuming it is in the DOM.

Will watch the Margin Convention and play around more with d3 before I ask for more—thank you so much again for being so helpful!

Lucas

Sorry, my bad - I meant tick labels :slight_smile:

I made a very simple example of margin convention:

https://codepen.io/sitek94/pen/GRjLmKy?editors=0010

Imagine that the <rect> is your barchart and by changing the margin values you’re making space for the axes.

Play around with the values to see how it works :wink:

Okay! I finally got to the Margin Convention stuff but I think this is a true “one step forward, two steps back” for me, at least right now :laughing:

Here’s my new Pen. I rewrote it based on your code + Curran’s video, although instead of setting a rect’s width to innerWidth and height to innerHeight I set a g like that because the whole group needs to move.

I refactored all of the code out into a functional component like Curran does and moved most of my code into there, using my newly translated/resized “g” element instead of my original svg. Nothing shows up!

I tried to start from the beginning and just get something to show up. First, I tested to make sure the data was still fetching on line 85, which it is, and then I tried the following code to just get some text to show up on the page (because I seriously cannot see anything), this is the code I used (lines 87-94):

  //testing out to see if I can get anything to display 
    g.selectAll('text')
    .data([null])
    .enter()
    .attr("x", 10)
    .attr("y", 10)
    .text("hi!")
    .attr("color", black)

It seems like I should use the Margin Convention on all of the following D3 projects as well (it just seems like good practice ) so I’m at a bit of a standstill not being able to get things to show up with it. It seems like this is probably a pretty simple fix but searches for “nothing showed up after d3 margin convention” and related phrases have not yielded anything. Any ideas?

Yeah, yeah, the rect was just an example to illustrate the idea.

After selecting the text and entering the data you have to append it:

g.selectAll('text')
  .data([null])
  .enter()
  .append('text')

Now the text should render :wink:

Regarding the rest of the code, when you try to render rects there are some variables that are not defined (bar, xScale, yScale) so I’d start debugging from there.

Maybe my google is better but these are my search results for “d3 margin convention” :smiley:

Margin Convention / D3 / Observable
Margin Convention · GitHub
How to understand the margin convention and axes in d3+svg
Margin Convention with D3 - bl.ocks.org

Also, here is a link to my barchart, where I tried to follow some of the techniques used by Curran in his videos, maybe you’ll find something useful there, good luck :wink:

Text appending worked! I meant issues specifically issues related to visibility and margin convention! Regardless, the resources you sent were awesome! I passed the tests and here was my final—thank you again!

1 Like

Happy to help :smiley: I see that all the tests are passing now, good job :slight_smile:

1 Like