D3 Nested & Independent General Update Pattern
This example demonstrates a nested General Update Pattern where each fruit group contains an independent, data-driven set of rectangles. The code shows how to use `selection.each` with the old-school `function` notation to access `this`, then create a new D3 selection via `select` for each `<g>` element. This allows a different number of rectangles per fruit, with sizes varying by fruit type. The visualization responds to data changes—adding, removing, and modifying fruits—updating both the outer groups and their inner rectangles through separate update patterns. It renders to SVG using D3 v6.
AI-generated descriptionA response to a question in the D3 Slack about different numbers of nested rectangles.
Original question by May Tan:
What i'm trying to do is add varying number of rectangles based on "num" in the data. The size of rectangle depends on the type of fruit. I realise that the rect size did update when the apple is changed into a lemon. However rect size didn't update on the last update when apple was eaten. My question is how do I write the selections when the data join is not based on number of array items, but range of some data. I am also sure i'm writing the update part wrongly as the size of rect did not get updated. Thanks for your help!
Answer:
Ahh I see what you mean. You want to essentially "break out" into a new update pattern, within each
<g>element, so that each has its own unique data driven collection of rectangles. Here's a solution for it:
const groups = groupsEnter.merge(groupsUpdate);
groups.each(function (d) {
const innerGroup = select(this);
const rects = innerGroup
.selectAll('rect')
.data((d) => d3.range(d.num).map(() => d));
rects
.enter()
.append('rect')
.attr('height', '30px')
.attr('stroke', 'black')
.merge(rects)
.attr('y', (d, i) => -40 * (i + 1))
.attr('width', (d) => radiusScale(d.type));
rects.exit().remove();
});
The trick is to use
selection.each(and the old schoolfunctionnotation to accessthis) to isolate the DOM nodes for the groups (exposed by D3 asthis), then useselectto create a new D3 selection for each individual<g>element. With this in hand, we can have another nested but totally independent General Update Pattern, allowing us to make a different number of rectangles for each group.