Skip to content

Why isn’ t this selecting and changing the attributes in D3?

I have a simple data object called data that contains some radii , co-ordinates and colours I wish to use for my circles. However I want to now make them all orange but the last line of code does not seem to run ?

const myCircles = svg.selectAll()
.data(data);

myCircles.enter().append('circle')
    .attr('cx' , (d) => d.x)
    .attr('cy' , (d) => d.y)
    .attr('r' , (d) => d.radius )
    .attr('fill' , (d) => d.color )

myCircles.attr('fill' , 'orange');

Other things I tried that did not work

I tried the line

d3.selectAll(myCircles).attr('fill' , 'orange');

And I tried

svg.selectAll(myCircles).attr('fill' , 'orange');

But both times recive the error: d3.v7.min.js:2 Uncaught DOMException: Failed to execute ‘querySelectorAll’ on ‘Element’: ‘[object Object]’ is not a valid selector.

What does work but I do not want it

d3.selectAll('circle').attr('fill' , 'orange')

Because I would like to select the circles by the variable myCircles and not using the d3 tag “circle” as I intend on making more circles later.

Answer

The myCircles variable is empty because it is only the update selection, and not the enter selection that appended the circles. If you need a variable to hold the appended circles, you can assign the enter selection to it:

const myCircles = svg.selectAll()
.data(data);

const myOrangeCircles = myCircles.enter().append('circle')
    .attr('cx' , (d) => d.x)
    .attr('cy' , (d) => d.y)
    .attr('r' , (d) => d.radius )
    .attr('fill' , (d) => d.color )

myOrangeCircles.attr('fill' , 'orange');

A good resource I recommend to learn more about those details is the official General Update Pattern Tutorial


To complement:

Instead of variables, you can also use classes to differentiate between objects. For example, if you append the circles with a class, you can later use selectAll to retrieve only the circles that match the class:

myCircles.enter().append('circle')
    .attr('cx' , (d) => d.x)
    .attr('cy' , (d) => d.y)
    .attr('r' , (d) => d.radius )
    .attr('fill' , (d) => d.color )
    .classed('myOrangeCircle', true)

svg.selectAll('circle.myOrangeCircle').attr('fill' , 'orange');