score:2

Accepted answer

i think your problem here is confusion around the nest function and that your nest variable isn't holding a reference to that function but your data instead.

that said, i find your code overly confusing and not written to how you should be using d3 data binding abilities. so here's my commented refactor working example:

<!doctype html>

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

  <body>
    <input type="radio" id="passed" name="stack" value="passed" />
    <label for="passed">passed</label><br />
    <input type="radio" id="category" name="stack" value="category" checked />
    <label for="category">category</label><br />
    <input type="radio" id="owner" name="stack" value="owner" />
    <label for="owner">owner</label>

    <div id="chart"></div>
    <br/><br/>
    <div id="legend"></div>
    <script>
      var doc = url.createobjecturl(
        new blob([
          `passed,category,owner,dup
yes,msg,hailey,yes
yes,msg,hailey,yes
yes,doc,hailey,yes
yes,doc,robert,yes
yes,msg,laquila,yes
no,spreadsheet,hailey,yes`,
        ])
      );

      // had to switch to csv for stacksnippet editor
      d3.csv(doc)
        .row(function (d) {
          return {
            passed: d.passed,
            category: d.category,
            owner: d.owner,
            dup: d.dup,
          };
        })
        .get(function (error, data) {

          // container for legend
          var legend = d3
            .select('#legend')
            //make the legend
            .append('svg')
            .attr('class', 'legend');

          // initial draw
          drawlegend('category');

          // function to redraw legend
          // based on d3 enter, update, exit
          function drawlegend(currentselection) {

            // apply nest function for new selection
            let nesteddata = d3
              .nest()
              .sortkeys(d3.descending)
              .key(function (d) {
                return d[currentselection];
              }).entries(data);

            // update selection
            let lu = legend
              .selectall('g')
              // the key function here is important
              // so that d3 can calculate the enter, update, exit
              .data(nesteddata, d => d.key);

            // exit selection
            lu.exit().remove();

            // enter selection
            // add container g
            let le = lu
              .enter()
              .append('g')
              .attr('transform', function (d, i) {
                return 'translate(0,' + i * 25 + ')';
              });

            // on enter add rect
            le.append('rect')
              .attr('class', 'rect')
              .attr('width', 18)
              .attr('height', 18)
              .style('fill', function (d,i) {
                return d3.schemecategory20[i];
              })
              .style('stroke', 'grey');

            // on enter add text
            le.append('text')
              .attr('x', 24)
              .attr('y', 9)
              .attr('dy', '.35em');

            // enter + update
            lu = le.merge(lu);

            // on enter or update, change text
            lu.selectall('text')
              .text(function(d){
                return d.key;
              });
          }

          d3.selectall("input[name='stack']").on('change', function (d) {
            drawlegend(this.value);
          });
        });
    </script>
  </body>
</html>


Related Query

More Query from same tag