I am currently reading "Data Visualization with D3 4.x Cookbook Second Edition".The data update mode is mentioned in chapter3.Sometimes the author uses merge() to achieve data update, but sometimes the author uses selectAll() to achieve. I have found that in some cases they are not interchangeable. I'm confused right now and I want to know, how can I determine which way I should do in data update.
In the 3.2.2,the author uses merge() to achieve data update
function render(data) { // <- B
var bars = d3.select("body").selectAll("div.h-bar") // <- C
.data(data); // Update <- D
// Enter
bars.enter() // <- E
.append("div") // <- F
.attr("class", "h-bar") // <- G
.merge(bars) // Enter + Update <- H
.style("width", function (d) {
return (d * 3) + "px"; // <- I
})
.text(function (d) {
return d; // <- J
});
// Exit
bars.exit() // <- K
.remove();
}
In the 3.6.2,the author uses selectAll() to achieve data update
function render(data, category) {
var bars = d3.select("body").selectAll("div.h-bar") // <-B
.data(data);
// Enter
bars.enter()
.append("div") // <-C
.attr("class", "h-bar")
//.merge(bars)
.style("width", function (d) {
return (d.expense * 5) + "px";}
)
.append("span") // <-D
.text(function (d) {
return d.category;
});
// Update
d3.selectAll("div.h-bar").attr("class", "h-bar");
// Filter
bars.filter(function (d, i) { // <-E
return d.category == category;
})
.classed("selected", true);
}
I really need your help! Thanks!
That's not the update selection (that would be bars), that's just the strange way the author designed for removing the class selected from the bars.
You see, when you click those buttons, the divs with the class selected become red-ish, while the other divs stay blue. So, the author is using this...
d3.selectAll("div.h-bar").attr("class", "h-bar")
...to remove the selected class, because attr("class", "foo") will override any existing class (see my answer here).
What strikes me as strange is that author, Nick Zhu, is quite good, I can't understand why he is doing that for removing a class. He could simply do:
bars.classed("selected", function (d) {
return d.category == category;
});
And here is the proof that it works (I'm copying his code from his GitHub repo):
body {
font-family: "helvetica";
}
button {
margin: 0 7px 0 0;
background-color: #f5f5f5;
border: 1px solid #dedede;
border-top: 1px solid #eee;
border-left: 1px solid #eee;
font-size: 12px;
line-height: 130%;
text-decoration: none;
font-weight: bold;
color: #565656;
cursor: pointer;
}
.box {
width: 200px;
height: 200px;
margin: 40px;
float: left;
text-align: center;
border: #969696 solid thin;
padding: 5px;
}
.red {
background-color: #e9967a;
color: #f0f8ff;
}
.blue {
background-color: #add8e6;
color: #f0f8ff;
}
.cell {
min-width: 40px;
min-height: 20px;
margin: 5px;
float: left;
text-align: center;
border: #969696 solid thin;
padding: 5px;
}
.fixed-cell {
min-width: 40px;
min-height: 20px;
margin: 5px;
position: fixed;
text-align: center;
border: #969696 solid thin;
padding: 5px;
}
.h-bar {
min-height: 15px;
min-width: 10px;
background-color: steelblue;
margin-bottom: 2px;
font-size: 11px;
color: #f0f8ff;
text-align: right;
padding-right: 2px;
}
.v-bar {
min-height: 1px;
min-width: 30px;
background-color: #4682b4;
margin-right: 2px;
font-size: 10px;
color: #f0f8ff;
text-align: center;
width: 10px;
display: inline-block;
}
.baseline {
height: 1px;
background-color: black;
}
.clear {
clear: both;
}
.selected {
background-color: #f08080;
}
.control-group {
padding-top: 10px;
margin: 10px;
}
.table {
width: 70%;
}
.table td,
th {
padding: 5px;
}
.table-header {
background-color: #00AFEF;
font-weight: bold;
}
.table-row-odd {
background-color: #f0f8ff;
}
.table-row-odd {
background-color: #d3d3d3;
}
.code {
display: inline-block;
font-style: italic;
background-color: #d3d3d3;
border: #969696 solid thin;
padding: 10px;
margin-top: 10px;
margin-bottom: 10px;
}
.countdown {
width: 150px;
height: 150px;
font-size: 5em;
font-weight: bold;
}
.axis .grid-line {
stroke: black;
shape-rendering: crispEdges;
stroke-opacity: .2;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 2;
}
.dot {
fill: #fff;
stroke: steelblue;
}
.area {
stroke: none;
fill: steelblue;
fill-opacity: .2;
}
.pie text {
fill: white;
font-weight: bold;
}
._0 {
stroke: none;
fill: darkred;
fill-opacity: .7;
}
._1 {
stroke: none;
fill: red;
fill-opacity: .7;
}
._2 {
stroke: none;
fill: blue;
fill-opacity: .7;
}
._3 {
stroke: none;
fill: green;
fill-opacity: .7;
}
._4 {
stroke: none;
fill: yellow;
fill-opacity: .7;
}
._5 {
stroke: none;
fill: blueviolet;
fill-opacity: .7;
}
.bubble {
fill-opacity: .3;
}
.bar {
stroke: none;
fill: steelblue;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Data Filter</title>
<script src="https://d3js.org/d3.v7.min.js"></script>
</head>
<body>
<script type="text/javascript">
var data = [ // <-A
{
expense: 10,
category: "Retail"
},
{
expense: 15,
category: "Gas"
},
{
expense: 30,
category: "Retail"
},
{
expense: 50,
category: "Dining"
},
{
expense: 80,
category: "Gas"
},
{
expense: 65,
category: "Retail"
},
{
expense: 55,
category: "Gas"
},
{
expense: 30,
category: "Dining"
},
{
expense: 20,
category: "Retail"
},
{
expense: 10,
category: "Dining"
},
{
expense: 8,
category: "Gas"
}
];
function render(data, category) {
var bars = d3.select("body").selectAll("div.h-bar") // <-B
.data(data);
// Enter
bars.enter()
.append("div") // <-C
.attr("class", "h-bar")
.style("width", function(d) {
return (d.expense * 5) + "px";
})
.append("span") // <-D
.text(function(d) {
return d.category;
});
// Update, COMMENTED OUT!
//d3.selectAll("div.h-bar").attr("class", "h-bar");
// Filter
bars.classed("selected", function(d, i) { // <-E
return d.category == category;
});
}
render(data);
function select(category) {
render(data, category);
}
</script>
<div class="control-group">
<button onclick="select('Retail')">
Retail
</button>
<button onclick="select('Gas')">
Gas
</button>
<button onclick="select('Dining')">
Dining
</button>
<button onclick="select()">
Clear
</button>
</div>
</body>
</html>
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