neuquen
neuquen

Reputation: 4169

D3 V4 - Using merge with general update pattern

I was able to successfully use the enter/update/exit logic to update my visualization, however, I'm doing so without using the new .merge() function outlined here: https://github.com/d3/d3/blob/master/CHANGES.md#selections-d3-selection so something makes me think I'm still doing it the v3 way. Whenever I try to use the .merge() function based on the documentation, it always breaks it.

I'm hoping you guys can help me figure out how to update the logic and do it the v4 way.

For example, in the following code I join the data to <g> elements and then nest other elements (<path> and <text>) inside of the <g> elements. So for each block of code where I append data to vis.group I need to write an identical block of code which calls the dataJoin for the update.

// DATA JOIN
var dataJoin = vis.clipPath.selectAll(".group")
  .data(vis.displayData);

// ENTER
vis.group = dataJoin.enter().append("g")
  .attr("class", "group")
  .attr("transform", function(d) {
    return "translate(0," + vis.y(d.registrationEndDate) + ")";
  });

// UPDATE
dataJoin
  .attr("transform", function(d) {
    return "translate(0," + vis.y(d.registrationEndDate) + ")";
  });

// ENTER
var path = vis.group.append("path")
  .attr("class", "line")
  .style("opacity", 0.1)
  .style("fill", function(d) {
    if (d.type === "currentEmployments") {
      return "#50A2DA";
    }
  })
  .attr("d", function(d) {
    return addPath(d, vis);
  });

// UPDATE
dataJoin.select(".line")
  .attr("d", function(d) {
    return addPath(d, vis);
  });

...

All of it seems way too repetitive, and I thought v4 was supposed to fix that by allowing me to use .merge(), but when I try something like the below, it doesn't work:

// ENTER
var path = vis.group.append("path")
  .attr("class", "line")
  .style("opacity", 0.1)
  .style("fill", function(d) {
    if (d.type === "currentEmployments") {
      return "#50A2DA";
    }
  })
  .merge(dataJoin) // ENTER + UPDATE
    .attr("d", function(d) {
      return addPath(d, vis);
    });

I'm expecting to be able to combine the separate enter and update blocks into one combined enter + update block with merge. Am I wrong on the logic here?

FULL EXAMPLE: https://jsfiddle.net/bschxdjb/2/

Upvotes: 2

Views: 4920

Answers (1)

Chirag Kothari
Chirag Kothari

Reputation: 1410

I think, just the selection passed to the merge function is incorrect. Check updated fiddle:

  // ENTER
  vis.group = dataJoin.enter().append("g")
    .attr("class", "group");

  // UPDATE
  vis.group
    .merge(dataJoin)
    .attr("transform", function(d) {
      return "translate(0," + vis.y(d.registrationEndDate) + ")";
    });

  // ENTER
  var path = vis.group.append("path")
    .attr("class", "line")
    .style("opacity", 0.1)
    .style("fill", function(d) {
      if (d.type === "currentEmployments") {
        return "#50A2DA";
      }
    })
    .merge(dataJoin.select(".line"))
    .attr("d", function(d) {
      return addPath(d, vis);
    });


  // Append Firm Name
  vis.group.append("text")
    .attr("class", "firm-name")
    .style("font-weight", "bold")
    .style("fill", function(d) {
      if (d.type === "currentEmployments") {
        return "#50A2DA";
      }
    })
    .merge(dataJoin.select(".firm-name"))
    .text(function(d) {
      var label = d.name;
      return label;
    })
    .attr("transform", function(d) {
      var range = vis.y(d.registrationBeginDate) - vis.y(d.registrationEndDate);
      return "translate(50," + (range / 2) + ")";
    });


  // Append Year range
  vis.group.append("text")
    .attr("class", "years")
    .attr("fill", "#696969")
    .merge(dataJoin.select(".years"))
    .text(function(d) {
      var count = d3.timeYear.count(d.registrationBeginDate, d.registrationEndDate);
      var years = '';
      if (count > 1) {
        years = " (" + count + " years)";
      } else if (count == 1) {
        years = " (" + count + " year)";
      } else if (count < 1) {
        years = " (<1 year)";
      }
      var label = convertToYear(d.registrationBeginDate) + " - " + convertToYear(d.registrationEndDate) + years;
      return label;
    })
    .attr("transform", function(d) {
      var range = vis.y(d.registrationBeginDate) - vis.y(d.registrationEndDate);
      return "translate(50," + ((range / 2) + 15) + ")";
    });

Upvotes: 4

Related Questions