Updating a bar chart with .update, .enter, and .exit?
<p>I have made a simple bar chart. I want to update the bars (on the fly) by toggling between different subsets of my data. From what I've seen, there appears to be two approaches:</p>

<ol>
<li>Draw the chart, and on a button click (or whatever) remove the whole chart and redraw it.</li>
<li>Use different data selections to 'update', 'enter' and 'exit' the bars from the chart on a button click.</li>
</ol>

<p>I'm attempting option 2. Here's my code:</p>

<pre><code>// set dimensions
var margin = {top: 10, right: 20, bottom: 50, left: 100};
var height = 600 -margin.top - margin.bottom;
var width = 600 - margin.left - margin.right;

// set ranges
var x = d3.scale.linear().range([width, 0]);
var y = d3.scale.ordinal().rangeRoundBands([0, height], .05);

// define y axis
var yAxis = d3.svg.axis()
.scale(y)
.orient("left");

// add svg container
var svg = d3.select("#chart")
.append("svg")
.attr("height", height + margin.top + margin.bottom)
.attr("width", width + margin.left + margin.right)
.append("g")
.attr("transform", "translate(" + margin.left + "," + margin.top + ")");

// load data
d3.json("data.json", function(data) {

  // format data
  data.forEach(function(d) {
    d.enrols = +d.enrols;
  });

  // register click event
  d3.selectAll(".toggle").on("click", function() {
    render(this.id);
  });

  // initialise
  render("group-1");

  function render(selection) {

    // filter data
    var subset = data.filter(function(d) { return d.group === selection} );

    // scale range of data
    x.domain([0, d3.max(subset, function(d) { return d.enrols; })]);
    y.domain(subset.map(function(d) { return d.month; }));

    // update selection
    var bars = svg.selectAll(".bars")
    .data(subset, function(d) { return d.month; });

    // add bars
    bars.enter()
    .append("g")
    .attr("class", "bar")
    .attr("transform", function (d, i) {
      return "translate(0," + y(d.month) + ")";
    });

    bars.append("rect")
    .attr("height", y.rangeBand())
    .attr("width", function (d) {
      return width - x(d.enrols);
    });

    bars.append("text")
    .attr("x", function (d) {
      return width - x(d.enrols) - 15;
    })
    .attr("y", y.rangeBand() / 2)
    .attr("dy", ".35em")
    .text(function (d) {
      return d.enrols;
    });

    bars.exit().remove();

    // add y axis
    svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

  }

});
</code></pre>

<p>Problem is my old data never gets exited, the new bars are appended, but the old ones remain. I've read the theory of d3 selections, but I'm finding them hard to implement in practice.</p>

<p>Here is a <a href="http://codepen.io/24ma13wg/pen/Rowqmo" rel="nofollow noreferrer">codepen</a>. Here is <a href="http://codepen.io/24ma13wg/pen/vyYQbK.js" rel="nofollow noreferrer">data.json</a>.</p>