D3.js How to apply multiple classes when using a function
Solution 1
You just want a single function that does both things don't you. Something along these lines perhaps...
var circle = svg.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("class", function(d) {
var c = "";
if (d["Set"] == 1)
{
c = "set-1";
}
if (d["Set"] == 2)
{
c = "set-2";
}
if (d["Year"] == 2012)
{
c += " 2012";
}
if (d["Year"] == 2013)
{
c += " 2013;
}
return c;
});
Solution 2
There is an alternative approach that can be useful. You can assign or remove classes from an element using selection.classed('class-name', true)
or selection.classed('class-name', false)
:
var circle = svg.selectAll("circle")
.data(data)
.enter()
.append('circle')
.classed('2012', function(d) { return d['Year'] === 2012; })
.classed('2013', function(d) { return d['Year'] === 2013; })
.classed('set-1', function(d) { return d['Set'] === 1; })
.classed('set-2', function(d) { return d['Set'] === 2; });
I prefer this way because you can remove the classes from an element using the same syntax.
Solution 3
Update
Seems, this approach no longer acceptable for D3.js v5+
Original answer
You can also use a hash as argument of classed
function:
var circle = svg.selectAll("circle")
.data(data)
.enter()
.append('circle')
.classed({
'2012': function(d) { return d['Year'] === 2012; },
'2013': function(d) { return d['Year'] === 2013; },
'set-1': function(d) { return d['Set'] === 1; },
'set-2': function(d) { return d['Set'] === 2; }
});
Related videos on Youtube
Dally
Updated on April 10, 2020Comments
-
Dally about 4 years
I'm currently using D3.js and have come across a problem that I just can't seem to solve.
I have a CSV that has a column named "Set" and a column named "Year". I want to pull the values from these columns and use them as class names. This is what I currently have...
var circle = svg.selectAll("circle") .data(data) .enter() .append("circle") .attr("class", function(d) { if (d["Set"] == 1) { return "set-1"; } if (d["Set"] == 2) { return "set-2"; } });
This works perfectly fine and gives each data-point a class name. When I try the following however, the "Set" class names are over written by the "Year" class names.
var circle = svg.selectAll("circle") .data(data) .enter() .append("circle") .attr("class", function(d) { if (d["Set"] == 1) { return "set-1"; } if (d["Set"] == 2) { return "set-2"; } .attr("class", function(d) { if (d["Year"] == 2012) { return "2012"; } if (d["Year"] == 2013) { return "2013; } });
How can this code be rectified so that it adds on additional class names as opposed to over-writing them.
Hope someone can help.
-
gaynorvader about 11 yearsHave you considered using jQuery? It has a nice
addClass()
method. -
Dally about 11 yearsBut how do I access the .CSV and apply the class to the correct data nodes?
-
gaynorvader about 11 yearsCan you add the class after loading in the CSV file?
-
-
Dally about 11 yearsYou sir are an absolute genius and have saved me a shed load of time.
-
Lars Kotthoff about 11 yearsYou can also concatenate directly:
.attr("class", function(d) { "set-" + d["Set"] + " " + d["Year"] })
. -
rmbianchi about 10 yearsvery nice answer! I like the suggestion of using the smart D3 classed() method. +1!
-
Billy Moon almost 9 years@LarsKotthoff I think you need a
return
in there no..? -
D_Bye almost 9 yearsan even better reason to use
classed
(instead ofattr('class'...
is that it won't clear other classes already assigned to the element. -
morels almost 8 yearsdislike this diy. Much better the OO approach from Pablo and @Ivan