Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

212
Views
Why is g element found in enter but not in update step in d3.js?

I am parsing an xml string and display it as a tree in d3.js. I can build the whole tree in the 'enter' step, but now I want to make it interactive and pull out the configuration into an update step. I'm following https://stackoverflow.com/a/24912466 to implement the general update pattern but I can't seem to set the attribute to the g element outside the enter step:

const svg = d3.select("#canvas");

const xmlAsText = `
      <root attrib1="foo" att2="foO">
      <child1 attrib1="ba">zwei</child1>
      <child2>eins</child2>
      </root>`;
treeDataXml = (new DOMParser()).parseFromString(xmlAsText, "text/xml");

let hierarchy = d3.hierarchy(treeDataXml.children[0], d => d.children);
  
nodesData = d3.tree()(hierarchy);

var myGroups =  svg.selectAll("g").data(nodesData.descendants());

myGroupsEnter = myGroups.enter().append("g")
// 1) works          
//myGroupsEnter       .attr("class", "x");
// 2) doesn't work
myGroups.select("g").attr("class", "x");

console.log(document.getElementById("canvas").childNodes[0].attributes[0])
alert(document.getElementById("canvas")
              .childNodes[0].attributes.length)
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<svg id="canvas"></svg>
with 1) I get

<body>
  <svg id="canvas">
    <g class="x"></g>
    <g class="x"></g>
    <g class="x"></g>
  </svg>
</body>

but with 2) it's just:

<body>
  <svg id="canvas">
    <g></g>
    <g></g>
    <g></g>
  </svg>
</body>

I would expect that with myGroups.select("g").attr("class", "x") the previously entered <g>s will all be selected and have their attribute class set to "x". Why doesn't this work? How can I fix this?

about 4 years ago · Santiago Trujillo
1 answers
Answer question

0

Selections are immutable, myGroups is an empty selection: it doesn't contain any DOM elements yet. As this selection is the update selection, this makes sense, there is nothing to update.

The selection myGroupsEnter contains the newly created elements. Entering elements does not modify myGroups, this remains an empty selection. This explains why myGroupsEnter.attr("class", "x"); works and myGroups.select("g").attr("class", "x"); does not.

D3 v3 and earlier added newly entered elements in the update selection, which is why some examples might be misleading, but as this behavior was not explicit it was removed

Often you want to combine the entered and updated elements into one selection, you can use:

let combined = myGroups.merge(myGroupsEnter);

This way regardless of whether you are entering all elements, updating all elements, or entering some and updating others you can modify all elements that exist (that are not exited).

about 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!