The chart takes both revenue and profit data it updates for the first second and .remove().exit() The function doesn't remove data Help me out.
Here is the link for stackblitz
import { Component, OnInit } from '@angular/core';
import * as d3 from 'd3';
import * as d3Array from 'd3-array';
import * as d3Axis from 'd3-axis';
import * as d3Scale from 'd3-scale';
@Component({
selector: 'app-d3js',
templateUrl: './d3js.component.html',
styleUrls: ['./d3js.component.css']
})
export class D3jsComponent implements OnInit {
private width: number;
private height: number;
private margin = {top: 20, right: 20, bottom: 100, left: 100};
x: any;
y: any;
private svg: any;
private g: any;
private xaxisGroup: any;
private yaxisGroup:any;
value;
flag = true ;
ylabel;
label;
xlabel;
bardata;
starbucksData=[
{
"month": "January",
"revenue": 23432,
"profit": 8342
},
{
"month": "February",
"revenue": 19342,
"profit": 50342
},
{
"month": "March",
"revenue": 17443,
"profit": 35423
},
{
"month": "April",
"revenue": 26342,
"profit": 18432
},
{
"month": "May",
"revenue": 34213,
"profit": 29434
},
{
"month": "June",
"revenue": 50321,
"profit": 45343
},
{
"month": "July",
"revenue": 54273,
"profit": 47452
}
]
constructor() { }
ngOnInit() {
this.initsvg();
this.initdrawAxis();
this.initAxis();
this.axisLabel()
// this.drawbars()
this.d3update()
}
initsvg(){
this.svg = d3.select('svg');
this.width = +this.svg.attr('width') - this.margin.left - this.margin.right;
this.height = +this.svg.attr('height') - this.margin.top - this.margin.bottom;
this.g = this.svg.append('g')
.attr('transform', 'translate(' + this.margin.left + ',' + this.margin.top + ')');
}
//non repetable code.
initdrawAxis(){
this.xaxisGroup=this.g.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + this.height +")")
this.yaxisGroup=this.g.append("g")
.attr("class", "y axis")
}
initAxis(){
this.x = d3Scale.scaleBand().rangeRound([0, this.width]).padding(0.2);
this.y = d3Scale.scaleLinear().rangeRound([this.height, 0]);
}
axisLabel(){
this.ylabel =this.g.append("text")
.attr("class","y axis-label")
.attr("x", -(this.height/2))
.attr("y", -60)
.attr("font-size" , "20px")
.attr("text-anchor", "middle")
.attr("transform", "rotate(-90)")
this.xlabel=this.g.append("text")
.attr("class","x axis-label")
.attr("x", 190)
.attr("y", 330)
.attr("font-size" , "20px")
.attr("text-anchor", "middle")
.text("month");
}
drawbars(){
this.bardata = this.g.selectAll('.bar')
.data(this.starbucksData)
this.bardata.exit().remove()
console.log(this.bardata)
this.bardata
.attr('x', (d) => this.x(d.month))
.attr('y', (d) => this.y(d[this.value]))
.attr('width', this.x.bandwidth)
.attr('height', (d) => this.height - this.y(d[this.value]) )
.attr('fill','blue')
console.log(this.bardata)
this.bardata
.enter()
.append("rect")
.attr('x', (d) => this.x(d.month))
.attr('y', (d) => this.y(d[this.value]))
.attr('width', this.x.bandwidth)
.attr('height', (d) => this.height - this.y(d[this.value]) )
.attr('fill','grey')
console.log(this.bardata)
}
d3update(){
d3.interval((d)=>{
this.updatabledata()
this.flag = !(this.flag)
console.log(this.flag)
}, 1000);
this.updatabledata()
}
updatabledata(){
this.value = this.flag ? "revenue" : "profit"
console.log(this.value)
this.x.domain(this.starbucksData.map(function(d){ return d.month }));
this.y.domain([0, d3Array.max(this.starbucksData, (d) => d[this.value])]);
var xAxisCall = d3.axisBottom(this.x)
this.xaxisGroup.call(xAxisCall);
var yAxisCall = d3.axisLeft(this.y)
.tickFormat(function(d){ return "$" + d; })
this.yaxisGroup.call(yAxisCall);
this.drawbars()
this.label = this.flag ? this.ylabel.text("profit") : this.ylabel.text("revenue")
}
}
On your
drawbars()
function your missing a key step to add the class name.bar
to your elements. That class name is used on the mainselectorAll('.bar')
so it can find the elements on re-renderingthe key line