I've the a node like:
<div>
<svg ...>
<g class="graph">
<path class="myarea" d="...AAA..." pos="p1"> </path>
</g>
<g class="graph">
<path class="myarea" d="...BBB..." pos="p2"> </path>
</g>
<g class="graph">
<path class="myarea" d="...CCC..." pos="p3"> </path>
</g>
/svg>
</div>
I am trying to select a specific node (e.g where d="...BBB...") which has the attribute pos='p2'
d3.selectAll(".myarea").each(function(d,i) {
console.log("-> ", d3.select(this).attr("pos"), d3.select(this).attr("pos") == 'p2' );
});
This produces/returns an arrays with all 3 entries:
-> p0 false
-> p1 true
-> p2 false
-> [Array(3)]
I am interested in selecting just one, in this case the one with .attr("pos") == 'p2'
so I'd like to return just one element.
I've tried with map()
and filter()
but without success.
What is the correct way to select a specific element based on an attribute value?
Selection.filter()
You could select a bunch of elements based on class, and then filter the selection with selection.filter()
:
svg.selectAll("whatever")
.filter(function() {
return d3.select(this).attr("col") == 2; // filter by single attribute
})
var svg = d3.select("svg");
svg.selectAll("rect")
.filter(function() {
return d3.select(this).attr("col") == 2
})
.attr("fill","orange");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
<rect width="20" height="20" x="5" y="5" col="1" row="1"></rect>
<rect width="20" height="20" x="30" y="5" col="2" row="1" ></rect>
<rect width="20" height="20" x="5" y="30" col="1" row="2" ></rect>
<rect width="20" height="20" x="30" y="30" col="2" row="2" ></rect>
</svg>
Using CSS selectors to select by attribute value
But, rather than selecting a bunch of elements and then filtering the selection, we can do everything in one step with the CSS selectors described here. This lets us select elements an attribute they have is equal to a specific value:
svg.selectAll("rect[col='2']")
var svg = d3.select("svg");
svg.selectAll("rect[col='2']")
.attr("fill","orange");
d3.selectAll("rect[col='1'][row='1']")
.attr("fill","steelblue");
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
<rect width="20" height="20" x="5" y="5" col="1" row="1"></rect>
<rect width="20" height="20" x="30" y="5" col="2" row="1" ></rect>
<rect width="20" height="20" x="5" y="30" col="1" row="2" ></rect>
<rect width="20" height="20" x="30" y="30" col="2" row="2" ></rect>
</svg>
In the above I also use:
d3.selectAll("rect[col='1'][row='1']") to select based on two attribute values.
You can also substitute look for a class rather than a generic tag, so for you this might look like:
d3.selectAll(".myarea[d='BBB'][pos='p2']")
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With