mike628
mike628

Reputation: 49321

Passing an object property to D3 'enter()'

I have an object with many properties and I am trying to create a bar chart by passing a specific property to the barChart function below. But when it gets to the attr, the properyItem is undefined. Not sure how to do this. If I hardcode the property name it works (eg: d.MURDER).

var barChart = function(propertyItem) {
    if (propertyItem == null) {
        propertyItem = "ROBBERY";
    }
    var svg = d3.select("body").append("svg");
    svg.attr("width", w).attr("height", h);
    svg.selectAll("rect")
        .data(dataset)
        .enter()
        .append("rect")
        .attr("x", function(d, i) {
            return i * (w / dataset.length);
        })
        .attr("height", function(d) {
            return d.propertyItem * 4;
        })
        .attr("width", w / dataset.length - barPadding)
        .attr("y", function(d) {
            return h - d.propertyItem * 4;
        })
}

Upvotes: 0

Views: 139

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

Assuming that your propertyItem does exist inside dataset, the solution is simple: use bracket notation. For instance:

.attr("height", function(d) {
    return d[propertyItem] * 4;
});

The reason is that propertyItem inside your function is just a string. If you do...

d.propertyItem

... instead of looking for the same property of your string, the browser will look for a property literally named propertyItem. Let's show it:

var obj = {
  foo: "this is what I want!",
  propertyItem: "this is not what I want..."
};
var propertyItem = "foo";
console.log("obj.propertyItem returns: " + obj.propertyItem)
console.log("obj[propertyItem] returns: " + obj[propertyItem])

So, as I suppose there is no property literally named propertyItem in your dataset array, it returns undefined.

Here is a demo with some dummy data and your code, but using bracket notation:

var dataset = [{
  foo: 80,
  bar: 10
}, {
  foo: 30,
  bar: 12
}, {
  foo: 70,
  bar: 11
}, {
  foo: 42,
  bar: 17
}];
var w = 400,
  h = 200,
  barPadding = 10;
var barChart = function(propertyItem) {
  if (propertyItem == null) {
    propertyItem = "ROBBERY";
  }
  var svg = d3.select("body").append("svg");
  svg.attr("width", w).attr("height", h);
  svg.selectAll("rect")
    .data(dataset)
    .enter()
    .append("rect")
    .attr("x", function(d, i) {
      return i * (w / dataset.length);
    })
    .attr("height", function(d) {
      return d[propertyItem] * 4;
    })
    .attr("width", w / dataset.length - barPadding)
    .attr("y", function(d) {
      return h - d[propertyItem] * 4;
    })
}
barChart("foo")
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>

Upvotes: 1

Related Questions