user3676943
user3676943

Reputation: 923

In D3.js I am confused by behavior of exit()

Today I am learning about D3.js

I started by studying this content:

https://bost.ocks.org/mike/circles/

Most of it seems easy to understand and follow.

But I have a problem getting exit() to work.

I do understand the idea that I can use exit() to force elements in my DOM to synch with values in a JS array.

So I wrote some code to demonstrate this idea and my code fails.

I want to know how I can rewrite my JS so that exit() will force elements in my DOM to synch with values in a JS array.

<html>
<body>

Ref:
<a href='https://bost.ocks.org/mike/circles/' target='x'>
  https://bost.ocks.org/mike/circles/
</a>

<script src="https://d3js.org/d3.v3.min.js"  charset="utf-8"></script>

<script>
  // I should create 3 circles
  var svg1 = d3.select('body')
      .append('svg')
      .attr('id','svg1')
      .attr('width',800).selectAll("circle")
      .data([0, 1, 2])
    .enter()
      .append("circle")
      .attr("cy", 60)
      .attr("cx", function(d, i) { return i * 100 + 30 })
      .attr("r",  function(d)    { return 5+5*d })
  // So far so good. I see 3 circles

  // Now I should remove some.
  var mycircles_a = svg1.selectAll("circle")
    .data([99, 88])
  // I should ask D3 to make the data-array sync with the circle-elements:
  mycircles_a.exit().remove()
  // Above call fails for some reason; I still see 3 circles!
  // I should see 2 circles because mycircles_a is bound to an array with only 2 values.

  'bye'
</script>

</body>

</html>

Upvotes: 1

Views: 42

Answers (2)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

In your example svg1 is, itself, an "enter" selection.

Your code works just fine if you break the chain, making svg1 just a selection that creates the SVG:

  var svg1 = d3.select('body')
      .append('svg')
      .attr('id','svg1')
      .attr('width',800);

svg1.selectAll("circle")
      .data([0, 1, 2])
    .enter()
      .append("circle")
      .attr("cy", 60)
      .attr("cx", function(d, i) { return i * 100 + 30 })
      .attr("r",  function(d)    { return 5+5*d })
  
  var mycircles_a = svg1.selectAll("circle")
    .data([99, 88])
  
  mycircles_a.exit().remove()
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

Upvotes: 3

Eric Guan
Eric Guan

Reputation: 15992

You're not saving a reference to svg1 correctly.

https://jsfiddle.net/y008c61L/

var svg1 = d3.select('body')
      .append('svg')
      .attr('id','svg1')
      .attr('width',800);
svg1.selectAll("circle")
//...

Upvotes: 1

Related Questions