alexc
alexc

Reputation: 1310

Trying to update bar chart in d3.js

I'm trying to update and transition my data within a bar chart depending on the month.

I've been using this as a guide, but I'm not sure how I've gone wrong with my example. I'm sure I'm missing some key fundamentals of d3.js, but I'm not sure where. Hoping someone can point them out for me? Here is a plnk and some code;

http://plnkr.co/edit/l0jQgzf2LHOatc1t8S5M?p=preview

function draw() {

        updateData();


        x.domain(group.map(function(d) {
            return d.label;
        }));
        y.domain([0, 100]);

        // add axis


    svg.append("g")
            .attr("class", "x axis")
            .attr("transform", "translate(0," + height + ")")
            .call(xAxis)
            .selectAll("text")
            .style("text-anchor", "end")
            .attr("dx", "-.8em")
            .attr("dy", "-.55em")
            .attr("transform", "rotate(-90)");


        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            .append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 5)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text("Value");

        // Add bar chart
        var bar = svg.selectAll("compareBar")
            .data(group);
        bar
            .enter().append("rect")
            .attr('x', function(d) {
                return x(d.label);
            })
            .attr('y', function(d) {
                return y(d.value);
            })
            .attr('width', x.rangeBand())
            .attr('height', function(d) {
                return height - y(d.value);
            });


        bar.exit().remove();

        bar
            .transition()
            .duration(750)
            .attr("y", function(d) {
                return y(d.value);
            })
            .attr("height", function(d) {
                return height - y(d.value);
            });

        svg.select(".y.axis").remove(); // << this line added
        // Existing code to draw y-axis:
        svg.append("g")
            .attr("class", "y axis")
            .call(yAxis)
            .append("text")
            .attr("transform", "rotate(-90)")
            .attr("y", 6)
            .attr("dy", ".71em")
            .style("text-anchor", "end")
            .text("value");

    }

    $("ul#months li a").click(function() {
        $("#selectMonth").text($(this).text());
        draw();
    })


    draw();
});

Here's hoping I'm not a million miles away..

Thanks in advance for any help/advice!

Upvotes: 1

Views: 214

Answers (1)

Cyril Cherian
Cyril Cherian

Reputation: 32327

Your code is not working mainly because of 2 reasons:

Problem1:

You are doing this:

    var bar = svg.selectAll("compareBar")//what is compareBar?
        .data(group);

It should have been:

var bar = svg.selectAll("rect")//select all rectangle DOMs
  .data(group);

Problem 2:

You are setting the data like this to the rect bar:

    var bar = svg.selectAll("compareBar")//what is compareBar?
        .data(group);

It should have been:

    var bar = svg.selectAll("rect")
        .data(group, function(d){return d.value+d.label;});

To uniquely identify the data with the rectangle bar.

This 2 fixes will solve your current problem.

Fixed here

But you have lot of issues in the code.

1) You are drawing the y axis x axis again and again.

2) You want transition and that will not work.

For fixing all this pass a flag for create when flag is on, do the append like this:

if (create) {
  bar
    .enter().append("rect")
    .attr('x', function(d) {
      return x(d.label);
    })
    .attr('y', function(d) {
      return y(d.value);
    })
    .attr('width', x.rangeBand())
    .attr('height', function(d) {
      return height - y(d.value);
    });
  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis)
    .selectAll("text")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", "-.55em")
    .attr("transform", "rotate(-90)");


  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis)
    .append("text")
    .attr("transform", "rotate(-90)")
    .attr("y", 5)
    .attr("dy", ".71em")
    .style("text-anchor", "end")
    .text("Value");
}

In this case you avoid making the x and y axis + bars again and again.

And the transition will work for all the cases (update + create):

bar
  .transition()
  .duration(750)
  .attr("y", function(d) {
    return y(d.value);
  })
  .attr("height", function(d) {
    return height - y(d.value);
  });

working code here

Upvotes: 1

Related Questions