Skip to content Skip to sidebar Skip to footer

Set Multiple Attributes In D3 Without Knowing What They Are Going To Be Ahead Of Time

I am tying to set multiple attributes in d3 similar to what is done in this answer: https://stackoverflow.com/a/20822552/1112097, but I want to be able to pass a set of attributes

Solution 1:

It would be better if you changed your data to be in the following format:

   attributes: { 
     "cx": 0,
     "cy": 30,
     "r": 10
  },
   styles: {
     "fill: "#00ff00",
     "stroke": "#0000ff"
  }

This way you could simply do...

var elementEnter = element.enter()
    .append(function (d) {return d.type;})
    .attr("class", "element")
    .attr(function(d) {return d.attributes});
    .style(function(d) {return d.styles});

If you still want to keep your current format, you can do something like...

var elementEnter = element.enter()
    .append(function (d) {return d.type;})
    .attr("class", "element")
    .attr(function(d) {return arrToObj(d.attributes)});
    .style(function(d) {return arrToObj(d.styles)});

functionarrToObj(arr) {
   var obj = {};
   arr.forEach(function(keyValue){
     obj[keyValue.label] = keyValue.val;
   });
   return obj;
}

Solution 2:

Try this.

functionsetAttributesAndStyles(d){
    var attrs = {};
    d.attributes.forEach(function(a){       
        attrs[a.label] =  a.val;
    });
    var styles = {};
    d.styles.forEach(function(a){       
        styles[a.label] =  a.val;
    });
    d3.select(this).attr(attrs);
    d3.select(this).attr(styles);
}

var element = svg.selectAll(".element")
   .data(data, function(d) {return d.id;});

var elementEnter = element.enter()
   .append(function (d) {
      return svg.append(d.type).node(); //Returns the dom element
   })        
   .attr("class", "element")
   .each(setAttributesAndStyles);

Note that selection.append(name) statement expects the name as a constant string or a function that returns the DOM element to append.

Post a Comment for "Set Multiple Attributes In D3 Without Knowing What They Are Going To Be Ahead Of Time"