Accepted answer

Perhaps, what you want here is the .datum() function in d3. One of it's specific use-cases is to bind the same datum to multiple DOM elments (i.e. bind one datum to an entire d3 selection).

For example, d3.selectAll('div').datum({foo: 'bar'}) would bind the same object {foo: 'bar'} to all of the <div>...</div> elements currently existing on the document.

Quoting directly from

selection.datum([value])...If value is specified, sets the element's bound data to the specified value on all selected elements. If value is a constant, all elements are given the same data [sic]

(Somewhat ironically, he refers to the constant datum as "data" in the explanation of the .datum() function!)

However, this is a literal answer to your question; there may be a more design-oriented answer to your question which might explain the "conventional" d3-way of handling your overall objective... In which case, you should probably consult some tutorials like



Use "key" argument function.

A key function may be specified to control which datum is assigned to which element «This function is evaluated for each selected element, in order, […] The key function is then also evaluated for each new datum in data, […] the returned string is the datum’s key.

(Search «If a key function is not specified…» paragraph)

More details …

D3 binds data to elements. By default is uses the «join-by-index» method (first found element maps to datum at index 0 and so forth…). If join-by-index is not enough to appropriately identify elements, "key" should be used in order for D3 to appropriately synchronise input dataset during rendering phases: "update" (result of data() method call), "creation" enter selection, "removal" (exit selection).

Let's say we need to draw some legend, given the following dataset …

const dataSet = [
  [ 15, "#440154" ]
  [ 238.58, "#414487" ]
  // ...

we first decide to draw the coloured square using <rect> element.

const updateSelection ='rect').data(dataSet);
// join-by-index strategy is enough here so there is no need to supply the key fn arg
// Key function could be `d => d[0]` (given data source cannot produce two entries
// with value at index 0 being the same, uniqness is garanteed)

    .attr('width', 15).attr('height', 15)
    .style('fill', d => d[1])

// Dispose outdated elements

We now need a <text> element to be drawn for each given datum to visually expose numeric values. Keeping join-by-index (default) strategy would cause D3 to first draw both rect and text elements but since there can only be a single element bound to a specific datum key, only the first found element will be considered upon update phase and any other element having same datum key will end up in the exit selection and removed from the DOM as soon as the Selection remove method is called.

… If multiple elements have the same key, the duplicate elements are put into the exit selection …

A solution is to concatenate the numeric value with the element nodeName.

// Notice how the selector has changed
const updateSelection ='rect, text').data(dataSet, function(d) { 
      // Concatenate the numeric value with the element nodeName
      return `${d[0]}:${this.nodeName}`;
  , enterSelection = updateSelection.enter()

// Add rect element
    .append('rect').attr('width', 15).attr('height', 15)
    .style('fill', d => d[1])

// Add text label
    .text(d => d[0])

// Dispose outdated elements


I would create a g element for entry in myData:

groups ='body').append('svg')

and append shapes to those group elements individually:


Related Query

More Query from same tag