D3.js How to apply multiple classes when using a function

27,971

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; }
  });
Share:
27,971

Related videos on Youtube

Dally
Author by

Dally

Updated on April 10, 2020

Comments

  • Dally
    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
      gaynorvader about 11 years
      Have you considered using jQuery? It has a nice addClass() method.
    • Dally
      Dally about 11 years
      But how do I access the .CSV and apply the class to the correct data nodes?
    • gaynorvader
      gaynorvader about 11 years
      Can you add the class after loading in the CSV file?
  • Dally
    Dally about 11 years
    You sir are an absolute genius and have saved me a shed load of time.
  • Lars Kotthoff
    Lars Kotthoff about 11 years
    You can also concatenate directly: .attr("class", function(d) { "set-" + d["Set"] + " " + d["Year"] }).
  • rmbianchi
    rmbianchi about 10 years
    very nice answer! I like the suggestion of using the smart D3 classed() method. +1!
  • Billy Moon
    Billy Moon almost 9 years
    @LarsKotthoff I think you need a return in there no..?
  • D_Bye
    D_Bye almost 9 years
    an even better reason to use classed (instead of attr('class'... is that it won't clear other classes already assigned to the element.
  • morels
    morels almost 8 years
    dislike this diy. Much better the OO approach from Pablo and @Ivan