Update selection not working

I'm new to D3 and I am trying to display a simple d3 bar chart that changes which data attribute it is visualizing based on a dropdown menu - the data remains the same and I am displaying the same labels (x-axis) with each dropdown selection, just the labels should transition/change their ordering and the bar values should transition/change based on which attribute they are showing.

When the dropdown menu changes however, the transition (update) selection isn't getting called - it is only called when the chart loads for the first time. Therefore, based on the code, the y-Axis is changing its numerical values, but the heights always remain the same as they are initiated so the bars don't animate at all despite the labels changing.

updateChart(menuSelection) { // called when dropdown selection changes, and initially upon page load with default menuSelection
    // I sort the data by the attribute of the dropdown item selected
    this.myData.sort(function(a,b){
        if(menuSelection == 1) return b.count - a.count;
        else if(menuSelection == 2) return b.positiveCount - a.positiveCount;
        else return b.negativeCount - a.negativeCount;
    });

    var m = this.myData.length;
    var svg = d3.select(".chart"),
        margin = {top: 40, right: 25, bottom: 40, left: 25},
        width = +svg.attr("width") - margin.left - margin.right,
        height = +svg.attr("height") - margin.top - margin.bottom;
    var g = svg.select("g.rectGroup").attr("transform", "translate(" + margin.left + "," + margin.top + ")").attr("class", "rectGroup");
    if(g.empty()) {
        g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")").attr("class", "rectGroup");
    }

    var x = d3.scaleBand()
        .domain(myData.map(function(d) { return d._id; }))
        .range([0, width])
        .padding(0.08);

    var yMax = d3.max(this.myData, function(d) {
        if(this.menuSelection == 1) return d.count;
        else if(this.menuSelection == 2) return d.positiveCount;
        else return d.negativeCount;
    });
    var y = d3.scaleLinear()
        .domain([0, yMax])
        .range([height, 0]);

    var xAxis = d3.axisBottom()
        .scale(x);
    var yAxis = d3.axisLeft()
        .scale(y);

    var yz = getHeights(m, menuSelection, this.myData); // ARRAY OF HEIGHTS DEPENDING ON MENU DROP DOWN SELECTION

    var bars = g.selectAll(".bar")
        .data(this.myData, function(d) {
            return d._id; // KEY IS ITEM NAME FOR OBJECT CONSTANCY; ALL ITEMS ARE DISPLAYED REGARDLESS OF ATTRIBUTE SELECTED, BUT ORDER/VALUES CHANGE FOR EACH ITEM
        })
        .enter().append("rect")
        .attr("class", "bar")
        .attr("height", 0)
        .attr("y", height);

    bars.transition().duration(700)
        .attr("x", function(d) { return x(d._id); })
        .attr("width", x.bandwidth())
        .attr("y", function(d, i) { return y(yz[i])})
        .attr("height", function(d, i) {
            return height - y(yz[i])
        });

    bars.exit().remove();

    svg.selectAll(".axis").remove();

    var height_to_use = +svg.attr("height") - margin.bottom
    var xAxis_g = svg.append("g")
        .attr("class", "x axis")
        .attr("transform", "translate(" + margin.left + "," + height_to_use + ")")
        .call(xAxis)
        .selectAll(".tick text")
        .call(wrap, x.bandwidth());

    svg.append("g")
        .attr("class", "y axis")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .call(yAxis);

    function getHeights(m, menuSelection, data) {
      var values = [];
      for (var i = 0; i < m; ++i) {
        if(menuSelection == 1) {
          values[i] = data[i].count;
        } else if(menuSelection == 2) {
          values[i] = data[i].positiveCount;
        } else {
          values[i] = data[i].negativeCount;
        }
      }
      return values;
    }
}

Answers:

Answer

Actually, you don't have an update selection in your code.

For having an update selection, break up your "enter" selection, like this:

//this is the update selection
var bars = g.selectAll(".bar")
    .data(data, function(d) {
        return d._id;
    });

//and the remainder is the enter selection
bars.enter().append("rect")
    .attr("class", "bar")
    .attr("height", 0)
    .attr("y", height);

Also, it's worth mentioning that, since you don't have an update selection in your code, this...

bars.exit().remove();

... is useless.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us Javascript

©2020 All rights reserved.