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