Issue: I want to update the bars in my graph so that when the “Dreamworks” button is clicked, it appends new bars and gets rid of the old ones. I know it is an enter(), exit() issue, but I do not know exactly how to implement it.
Context: When my button is clicked, it activates a function that extracts the inner HTML of my button and uses it to filter my data so only observations from a company remain. The code works, but instead of getting rid of old bars, it appends the new bars on top of the old ones. When you look in the console, a new “g” element appears (which contains the new “rects”) every time the button is clicked. I lowered the opacity of the “rects” to show what is going on. I removed all exit() and remove() attempts from my code because nothing was working.
HTML Code:
<div class= "button-holder">
<button class= "button button-dreamworks">DreamWorks</button>
<button class= "button button-disney">Disney</button>
<button class= "button button-pixar">Pixar</button>
</div>
<div class = "chart chart1"></div>
JS Code:
async function drawBar() {
// 2. Create Chart Dimensions
const width = 600
let dimensions = {
width,
height: width*0.6,
margin: {
top: 30,
right: 10,
bottom: 50,
left: 50
}
}
dimensions.boundedWidth = dimensions.width
-dimensions.margin.right -dimensions.margin.left
dimensions.boundedHeight = dimensions.height
-dimensions.margin.top -dimensions.margin.left
// 3. Draw Canvas
const wrapper = d3.select(".chart1")
.append("svg")
.attr("width", dimensions.width)
.attr("height", dimensions.height)
// 4. Load Data
const raw_data = await d3.csv("./data/all_movie_data.csv")
const drawBarChart = function(company_name) {
const dataset = raw_data.filter(function(d){ return d["company"] == company_name })
const xAccessor = d => d["name"]
const yAccessor = d => parseFloat(d.budget)
let bounds = wrapper
.append("g")
.attr("class", "bounds")
.style(
"transform",
`translate(${dimensions.margin.left}px,${dimensions.margin.top}px)`
);
// 5. Create scales
const xScale = d3.scaleBand()
.domain(dataset.map(xAccessor))
.range([0,dimensions.boundedWidth])
.padding(0.4);
const yScale = d3.scaleLinear()
.domain(d3.extent(dataset,yAccessor))
.range([dimensions.boundedHeight, 0])
// 6. Draw Data
bounds.selectAll("rect")
.data(dataset)
.join("rect")
.attr("x", (d) => xScale(xAccessor(d)))
.attr("y", (d) => yScale(yAccessor(d)))
.attr("width", xScale.bandwidth())
.attr("height", (d) => dimensions.boundedHeight - yScale(yAccessor(d)))
.attr("fill", "blue");
}
//6. Interactions
drawBarChart("Pixar");
const button1 = d3.select(".button-dreamworks")
.node()
.addEventListener("click", onClick1)
function onClick1() {
const company = document.querySelector(".button-dreamworks").innerHTML;
drawBarChart(company);
}
}
drawBar();
You can find a version of my code in this code pen: https://codepen.io/larylc/pen/XWzbQGy
Everything is the same except for the data, which I just made up to show the issue.