score:2

Accepted answer

The data method in your second level has just one argument:

.data(function (d) {
    return d.value; 
});

For assigning the key function you have to pass a second argument. For instance:

.data(function(d) {
    return d.value
}, function(d) {
    return d.key
});

You can better see it in one line:

.data(function(d) { return d.value }, function(d) { return d.key });
//2nd arg after the comma ----------^

However, to facilitate human reading, I'd advise you to use different property names for level 1 and level 2. Right now everything is value and key, which can be hard to understand (not for the machine, though). For instance, in the above snippet, value refers to the first level array, while key refers to the second level array, not the first one... do you see the mess?

Here is a demo with your data:

var data = [{
    "key": "cat1",
    "value": [{
      "key": "subcatA",
      "value": 100
    }, {
      "key": "subcatB",
      "value": 200
    }]
  },
  {
    "key": "cat2",
    "value": [{
      "key": "subcatA",
      "value": 150
    }, {
      "key": "subcatB",
      "value": 250
    }]
  }
];

var body = d3.select("body");
var outer = body.selectAll(null)
  .data(data, function(d) {
    return d.key
  })
  .enter()
  .append("div")
  .attr("class", "outer");

var inner = outer.selectAll(null)
  .data(function(d) {
    return d.value
  }, function(d) {
    console.log("the key is: " + d.key)
    return d.key
  })
  .enter()
  .append("div")
  .html(function(d) {
    return d.key + " - " + d.value
  });
<script src="https://d3js.org/d3.v4.min.js"></script>


Related Query