I need to ensure that a div element has an svg child, so I do:
let svg = div.querySelector("svg") ? d3.select(div).select("svg") : d3.select(div).append("svg")
Is there a simple way to achive this with d3.js ?
(I realized that observablehq has a "DOM" functionality that eases this.)
The idiomatic D3 (a bit verbose) for what you want is normally this:
const svg = div.selectAll("svg")
.data([true])
.enter()
.append("svg");
What it does is basically selecting all SVGs inside the div. If there's one, it's returned in the selection. If there's none, one SVG is appended and returned in the selection. The [true] is just a way to show that the bound data doesn't matter, all that matters is we have a valid array with one element.
Here's a demo showing that the SVG is appended on the first loop interaction, but not on the following ones:
const div = d3.select("div");
for (let i = 0; i < 10; i++) {
console.log(`We have ${div.select("svg").size()} SVG so far`)
const svg = div.selectAll("svg")
.data([true])
.enter()
.append("svg");
};
svg {
background-color: teal;
}
<script src="https://d3js.org/d3.v7.min.js"></script>
<div></div>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With