Difference between selections when using 'attr ()'

I have a piece of code that is called by a button click.

const lines = svg.select('lines').selectAll('line').data(arr);
lines.enter().append('line');
lines
  .attr('x1', d => d)
  .attr('y1', d => d)
  .attr('x2', d => d+2)
  .attr('y2', d => d+2)
  .attr('stroke-width', 2);

      

And when I click the button, nothing appears, but when I click the button again, the lines can be seen.

So I tried to bind .attr () to .append () . Like this:

const lines = svg.select('lines').selectAll('line').data(arr);
    lines.enter().append('line')
      .attr('x1', d => d)
      .attr('y1', d => d)
      .attr('x2', d => d+2)
      .attr('y2', d => d+2)
      .attr('stroke-width', 2);

      

This time, the lines can be seen the first time the button is pressed.

I just want to know the reason for this behavior.

+3


source to share


2 answers


In your first piece of code, you are executing .attr

on a variable strings. This holds the selection update

(selection of those things that are already on the page). Since nothing exists, there is nothing to update.



In the second code snippet, you are executing .attr

on the object returned by the method .append

(via chaining). These things were added to the page only .enter

and are a choice enter

.

+6


source


In addition to @Mark's (correct) answer , it's worth mentioning that this snippet of yours will work in D3 v3.x!

What happened is that Mike Bostock, the creator of D3, introduced magical behavior in D3 v2, which he kept in D3 v3.x, but decided to drop D3 v4.x. To read more about it, take a look here: What Makes Software Good? This is what he says:

D3 2.0 made a change: adding to the input selection will now copy the incoming items to the update selection [...] D3 4.0 removes the enter.append magic. (In fact, D3 4.0 removes the distinction between enter and normal selection entirely: there is now only one selection class.)

This is a demo of your code using D3 v4.x. Nothing will appear, as you can see:



const arr = [10, 20, 30]
const svg = d3.select("svg");
const lines = svg.selectAll('line').data(arr);
lines.enter().append('line');
lines.attr('x1', d => d)
  .attr('y1', d => d)
  .attr('x2', d => d + 40)
  .attr('y2', d => d + 20)
  .attr('stroke-width', 2)
  .attr("stroke", "black");
      

<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
      

Run codeHide result


Now the same code using D3 v3:



const arr = [10, 20, 30]
const svg = d3.select("svg");
const lines = svg.selectAll('line').data(arr);
lines.enter().append('line');
lines.attr('x1', d => d)
  .attr('y1', d => d)
  .attr('x2', d => d + 40)
  .attr('y2', d => d + 20)
  .attr('stroke-width', 2)
  .attr("stroke", "black");
      

<script src="https://d3js.org/d3.v3.min.js"></script>
<svg></svg>
      

Run codeHide result


+4


source







All Articles