d3.js

Why d3.select(this) does not return expected node inside d3.selection.each call?


According to the documentation of d3.selection.each, this and nodes[i] should refer to the parent node, but d3.select(this) (commented line) does not refers to the div? What am I missing here?

import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
var body = d3.select('body');
  
var divs = body.selectAll('.test')
    .data(d3.range(3))
  .join('div')
    .attr('class', 'test');

divs.each((d, i, nodes) => {
//  d3.select(this).selectAll('span')
    d3.select(nodes[i]).selectAll('span')
    .data([1,2,3])
    .join('span')
        .text(i => `${d}.${i}`);
})

https://jsfiddle.net/z1dpgjvc/


Solution

  • ok, found the answer … this is because of the use of an arrow function, it seems that in that case this is not bound to the node but to the outer scope.

    the correct use is:

    import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
    var body = d3.select('body');
      
    var divs = body.selectAll('.test')
        .data(d3.range(3))
      .join('div')
        .attr('class', 'test');
    
    divs.each(function(d) {             // note the function instead of the =>
      d3.select(this).selectAll('span') // works like a charm
        .data([1,2,3])
        .join('span')
            .text(i => `${d}.${i}`);
    })
    

    source of the information: https://riptutorial.com/d3-js/example/27637/using--this--with-an-arrow-function