2

What exactly does extra select() on enter() selection do and why does it not have selectAll()?

Now here I am probably supposed to post more text to "meet your quality standards", but I am quite sure the question is precise enough and hopefully not too stupid. I spent few days reading through various d3 tutorials and docs, and this part still escaped from me.

2 Answers2

8

Calling select on the enter selection is rare; it is much more common to use append or insert instead. Yet the end result of all three of these methods is the same: it specifies how to instantiate elements in the enter selection.

When you perform a data-join, three new selections are returned:

  • the update selection: selected elements that correspond to the data
  • the exit selection: any leftover elements (no corresponding data)
  • the enter selection: any leftover data (no corresponding elements)

Since the enter selection is leftover data, there are by definition no corresponding elements. The enter selection thus initially contains placeholder nodes which you must instantiate into proper elements. You almost never see these nodes because you immediately tell D3 how to create the missing elements, typically by calling append or insert. These methods create new elements and insert them into the DOM. (The parent node is determined by the previous select, as described in the nested selections tutorial.)

In rare cases, you might want to do something beyond the standard append or insert for instantiating entering nodes. For example, the standard append method always creates elements of the same name (such as "div" or "rect"). If you wanted to specify the name dynamically, you could use select instead and pass in a function to create the new elements (as discussed in this thread in the d3-js mailing list):

enterSelection.select(function(d) {
  return this.appendChild(document.createElement(d.name));
});

In fact, if you look at how append is implemented, you'll see that it's just a wrapper on top of select. A slightly simplified implementation is:

d3.selection.prototype.append = function(name) {
  return this.select(function() {
    return this.appendChild(document.createElement(name));
  });
};

These example implementations are simplified because they don't deal with namespaced SVG elements. For this reason it's easier to use the built-in methods, and these examples are solely to explain how D3 works internally.

mbostock
  • 51,423
  • 13
  • 175
  • 129
2

Calling .select() on an .enter() selection does the same thing it does for other selections -- you can use it to narrow down what you select further. Having .selectAll() wouldn't really make sense as the .enter() selection refers to things that are not actually there yet. Therefore you would only be able to select the entire selection again (as there're no distinguishing characteristics).

Lars Kotthoff
  • 107,425
  • 16
  • 204
  • 204
  • I don't get it :( What could you select from "things that are not actually there yet"? I mean, I thought enter().select(...) is routed to enter selection parent node(s), otherwise it does not make sense? – user1652613 Sep 06 '12 at 18:39
  • Hmm, looks like I misunderstood slightly -- I guess the only reason to use `.select()` in this case would be for more elaborate manipulation of the new elements. See [this jsfiddle](http://jsfiddle.net/4cstE/1/) for an example of how to use `select` with a function that would allow you to do that (example adapted from the d3 API docs). – Lars Kotthoff Sep 06 '12 at 19:15
  • Thanks for that, it might also help if you drop a link to relevant api docs part where this example is discussed. – user1652613 Sep 06 '12 at 19:54
  • The example is in the [documentation for `.enter()`](https://github.com/mbostock/d3/wiki/Selections#wiki-enter). – Lars Kotthoff Sep 06 '12 at 20:00
  • But that one does not have select? I guess I will just have to study your example then. – user1652613 Sep 06 '12 at 20:45
  • So I did - and it looks like enter().select(...) simply returns the array of data in entering selection, transformed by argument function. Here: http://jsfiddle.net/7bjQ5/1/ this returned array does not have a prototype, so no non-Array methods attached, right? – user1652613 Sep 07 '12 at 13:33
  • I'm not entirely sure what you mean, but the what it returns is exactly what you would get for `.select()` in other contexts. – Lars Kotthoff Sep 07 '12 at 13:41
  • oh indeed, append is there directly on object. but if I use it, the result does not appear anywhere http://jsfiddle.net/7bjQ5/2/ any way, I am going to accept this answer - at least I am one step closer, knowing what to pass to select. – user1652613 Sep 07 '12 at 13:51