Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding enter() and exit()

Tags:

d3.js

From my understanding of the enter function in D3 the content of div after this code runs:

<body>
    <div>
        <p class="x"></p>
    </div>
    <script>
        d3.select('div')
            .selectAll('p')
            .data([3, 4])
            /**
             * if I uncomment this it works 
             * but I don't want to call the
             * same function twice
             */
            // .text(d => d + '')
            .enter()
            .append('p')
            .text(d => d + '');
    </script>
</body>

should be:

    <div>
        <p class="x">3</p>
        <p>4</p>
    </div>

but instead I get

    <div>
        <p class="x"></p>
        <p>4</p>
    </div>

1) I'm I missing something? From my understanding the 3 should be applied to the first p and the 4 to the appended one after the enter function.

2) Also I don't quite get the exit().remove() thing, from my understanding it should remove the appended p but it doesn't then what it is it good for?

like image 919
ilovelamp Avatar asked Apr 11 '17 21:04

ilovelamp


1 Answers

When you do this:

d3.select('div')
    .selectAll('p')

You're selecting all <p> elements inside the selected div. You have only one div (that doesn't matter, because select selects the first one it gets anyway...) and only one <p> element inside it.

Then, you bind the data:

.data([3, 4])

Thus, so far, we have:

  • 1 element in the selection
  • 2 data points in the data

And now comes the important part regarding the "enter" selection: you already have one <p> element in your selection. That <p> element gets the first datum, 3. The remaining datum is appended to a newly created p element, which is 4.

Your "enter" selection contains all data points without a corresponding element. As you can see, since you have 1 element in the selection and 2 data points, your "enter" selection has only 1 element. Let's show it (look at the console):

var enterSelection = d3.select('div')
  .selectAll('p')
  .data([3, 4])
  .enter()
  .append('p')
  .text(d=>d);

console.log("Elements in the enter selection: " + enterSelection.nodes().length)
<script src="https://d3js.org/d3.v4.min.js"></script>
<div>
  <p class="x"></p>
</div>

In a nutshell, you have to compare the selection with the data: if you have more data than elements, the extra data will be bound to elements belonging to the "enter" selection. If you have more elements than data, the extra elements without corresponding data belong to the "exit" selection. In your case, the "exit" selection is empty.

Finally, if you want to update the text of your existing <p> element, you have to use an "update" selection:

var p = d3.select('div')
  .selectAll('p')
  .data([3, 4]);

p.enter()
  .append('p')
  .merge(p)
  .text(d => d);
<script src="https://d3js.org/d3.v4.min.js"></script>
<div>
  <p class="x"></p>
</div>
like image 89
Gerardo Furtado Avatar answered Nov 28 '22 08:11

Gerardo Furtado