title: D3 removing previous bar chart on update of data
body: <p>I am having trouble removing bars from a bar chart when the data updates. I expected .exit().remove() to work. But when I update both bar charts are still there.</p>
  
  <p>A minimum version is running on <a href="https://shanegibney.github.io/d3-Draft-Update-Data/" rel="nofollow noreferrer">gh-pages</a>, you will need to use the dropdown menu to get it started. At the moment the first data file data1.json is not loading. </p>
  
  <p>When a file loads only the bars associated with names that were in the previous render are displayed. When the same file in the drop down menu is clicked again the other bars appear. So the file has to be clicked on twice to display correctly. </p>
  
  <p>If the initial render displays only the bars in common then this explains why it is blank when the page first loads, there is nothing in common. </p>
  
  <p>Anyway, obviously this isn't the behaviour I am looking for. </p>
  
  <p>And the code is on <a href="https://github.com/shanegibney/d3-Draft-Update-Data" rel="nofollow noreferrer">github</a> and on <a href="https://jsfiddle.net/ofey/1r4nr9jk/" rel="nofollow noreferrer">jsFiddle</a> </p>
  
  <pre><code>          var newRects0 = g0.selectAll(".bar")
              .data(data, function(d) {
                return d.name;
              });
  
            // newRects0.selectAll(".bar").remove();
            newRects0.enter()
              .append('rect')
              .attr('x', function(d, i) {
                return x(d.name);
              })
              // .attr('opacity', 0.33)
              .attr('width', x.bandwidth())
              .attr('y', height)
              .attr('height', 0)
              .attr("transform", "translate(0,0)")
              .style('fill', 'gray')
              .attr("class", function(d, i) {
                return "group" + i + " bar"
              });
  
            newRects0.exit().remove();
  
            newRects0.transition()
              .duration(100)
              .delay(function(d, i) {
                return i * 15
              })
              .attr("x", function(d) {
                return x(d.name);
              })
              .attr("y", function(d, i) {
                return y(d.clocktime);
              })
              .attr("height", function(d, i) {
                return height - y(d.clocktime)
              })
              .attr("width", x.bandwidth());
  </code></pre>
  
  <p>The x and y axes are changing correctly. </p>
  
  <p><strong><em>UPDATE:</em></strong> </p>
  
  <p>I am now trying to use Bostock's <a href="https://bl.ocks.org/mbostock/3808234" rel="nofollow noreferrer">Update Pattern III</a> The bars appear and then disappear after I think 750ms.</p>
  
  <p>I have greatly simplified the code, it is now on <a href="https://github.com/shanegibney/d3-Draft-Update-Data" rel="nofollow noreferrer">github</a>, <a href="https://shanegibney.github.io/d3-Draft-Update-Data/" rel="nofollow noreferrer">gh-pages</a>, and <a href="https://jsfiddle.net/ofey/1r4nr9jk/4/" rel="nofollow noreferrer">jsFiddle</a>.</p>
  
  <pre><code> &lt;!DOCTYPE html&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;style&gt;
    .container {
      margin-left: 0px;
    }
  &lt;/style&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js"&gt;&lt;/script&gt;
  &lt;script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" crossorigin="anonymous"&gt;
  &lt;script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/js/bootstrap.min.js" crossorigin="anonymous"&gt;&lt;/script&gt;
  
  &lt;body&gt;
    &lt;ul class="nav nav-tabs"&gt;
      &lt;li class="nav-item"&gt;
        &lt;a class="nav-link active" href="#"&gt;Home&lt;/a&gt;
      &lt;/li&gt;
      &lt;li class="nav-item dropdown"&gt;
        &lt;a class="nav-link dropdown-toggle" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false"&gt;Data&lt;/a&gt;
        &lt;div class="dropdown-menu"&gt;
          &lt;a class="dropdown-item" id="defaultInput" value="one" href="#"&gt;data1.json&lt;/a&gt;
          &lt;a class="dropdown-item" id="updateInput" value="two" href="#"&gt;data2.json&lt;/a&gt;
        &lt;/div&gt;
      &lt;/li&gt;
      &lt;li class="nav-item"&gt;
        &lt;a class="nav-link" href="#"&gt;Link&lt;/a&gt;
      &lt;/li&gt;
      &lt;li class="nav-item"&gt;
        &lt;a class="nav-link disabled" href="#"&gt;Disabled&lt;/a&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
    &lt;div class="container-fluid"&gt;
      &lt;div class="row"&gt;
        &lt;div class="col-md-12"&gt;
          &lt;div id="race_graph"&gt;
          &lt;/div&gt;
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  
    &lt;script src="https://d3js.org/d3.v4.min.js"&gt;&lt;/script&gt;
    &lt;script&gt;
      // set the dimensions and margins of the graph
      var margin = {
          top: 70,
          right: 50,
          bottom: 100,
          left: 80
        },
        width = 1400 - margin.left - margin.right,
        height = 600 - margin.top - margin.bottom;
  
      var parseTime = d3.timeParse("%M:%S");
      var timeformat = d3.timeFormat("%M:%S");
  
      // set the domains and ranges
      var x = d3.scaleBand()
        .range([0, width])
        .padding([0.6]);
  
      // temporal y-scale
      var y = d3.scaleTime()
        .range([height, 0]);
  
      var xAxis = d3.axisBottom(x);
  
      var yAxis = d3.axisLeft(y)
        .ticks(7)
        .tickFormat(d3.timeFormat("%M:%S"));
  
      // Add main graph svg
      var svg = d3.select("#race_graph")
        .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom);
  
      // Add groups for main bar chart
      var g0 = svg.append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
  
  
      function defaultFunction() {
        d3.json("data1.json", function(error, newdata) {
          if (error) throw error;
          data = newdata;
  
          data.forEach(function(d) {
            d.racetime = parseTime(d.racetime);
            d.handicap = parseTime(d.handicap);
            d.clocktime = parseTime(d.clocktime);
            d.place = +d.place;
            d.points = +d.points;
            d.raceplace = +d.raceplace;
            d.timeplace = +d.timeplace;
          })
          update();
        });
      }
  
      function updateFunction() {
        d3.json("data2.json", function(error, newdata) {
          if (error) throw error;
          data = newdata;
          data.forEach(function(d) {
            d.racetime = parseTime(d.racetime);
            d.handicap = parseTime(d.handicap);
            d.clocktime = parseTime(d.clocktime);
            d.place = +d.place;
            d.points = +d.points;
            d.raceplace = +d.raceplace;
            d.timeplace = +d.timeplace;
          })
          update(data);
        });
      }
  
      function update(err, newdata) {
  
        // set the domains
        x.domain(data.map(function(d) {
          return d.name
        }));
  
        // set domain temporal y-scale
        y.domain([parseTime('00:00'), d3.max(data, function(d) {
          return d.clocktime
        })]);
  
        // Add the X Axis
        svg.select(".x.axis").call(xAxis);
        svg.select(".x.axis").remove();
        svg.append("g")
          .attr("class", "x axis")
          .attr("transform", "translate(" + (margin.left) + "," + (height + margin.top) + ")")
          .call(xAxis)
          .selectAll("text")
          .attr("transform", "translate(-100,0)")
          .style("text-anchor", "end")
          .style("font", "7px times")
          .attr("class", function(d, i) {
            return "groupText" + i + " xAxisText"
          })
          .attr("dx", "-.8em")
          .attr("dy", ".15em")
          .attr("transform", "rotate(-75)");
  
        // Add the y axis on left
        svg.select(".y.axis").remove();
        svg.append("g")
          .attr("class", "y axis")
          .attr("transform", "translate(" + (margin.left) + "," + margin.top + ")")
          .call(yAxis);
  
        var t = d3.transition()
          .duration(4000);
  
        // JOIN new data with old elements
        var newRects0 = g0.selectAll(".bar")
          .data(data, function(d) {
            return d;
          });
  
        // EXIT old elements not present in new data
        newRects0.exit()
          .transition(t)
          .attr("x", function(d) {
            return x(d.name);
          })
          .attr("y", function(d, i) {
            return y(d.clocktime);
          })
          .attr("height", function(d, i) {
            return height - y(d.clocktime)
          })
          // .attr("width", x.bandwidth())
          .remove();
  
        // UPDATE old elements present in new data
        newRects0.attr("x", function(d) {
            return x(d.name);
          })
          .attr("y", function(d, i) {
            return y(d.clocktime);
          })
          .attr("height", function(d, i) {
            return height - y(d.clocktime)
          })
          // .attr("width", x.bandwidth())
          .style('fill', 'gray');
  
        // ENTER new elements present in new data
        newRects0.enter()
          .append('rect')
          .attr("x", function(d) {
            return x(d.name);
          })
          .attr("y", function(d, i) {
            return y(d.clocktime);
          })
          .attr("height", function(d, i) {
            return height - y(d.clocktime)
          })
          .attr("width", x.bandwidth())
          .style('fill', 'gray')
          .attr("class", function(d, i) {
            return "group" + i + " bar"
          });
  
      }; //closes update() function
  
      document.getElementById("defaultInput")
        .onclick = defaultFunction;
      document.getElementById("updateInput")
        .onclick = updateFunction;
      defaultFunction();
    &lt;/script&gt;
  &lt;/body&gt;
  </code></pre>
  
  <p>Thanks,</p>