javascript - Dynamically updating d3 bar chart -
this function runs on page load, , when data entered in form. draws graph fine on page load, doesn't redraw when new info submitted.
when log element after data join, shows updated length of data array, , updated number of elements, don't redraw. ideas, scanning code? feel it's close, i'm not understanding steps of data updating process.
this based on basic bar graph tutorial let's make bar chart, uses divs instead of svg elements, don't think should matter.
this.render = function(self){ if(self.data){ self.x = d3.scalelinear() .domain([0, d3.max(self.data.map(function(d) { return parseint(d.daily_count); })) ]) .range([0, 500]); var bars = d3.select("#chart") .selectall("div") .data(self.data) .enter().append('div') .attr('class', 'bar-container row'); console.log('chart', d3.select("#chart").data(self.data)); bars.append('div') .attr('class', 'label 4 columns') .text(function(d) {return d.date_string; }); bars.append("div") .attr('class', 'bar 8 columns') .style('background-color', function(d){ return (d.daily_count == 0 ? 'white' : '#1eaedb') }) .style('color', function(d){ return (d.daily_count == 0 ? 'red' : 'white') }) .style("width", function(d) { return self.x(d.daily_count) + "px"; }) .text(function(d) { return (d.daily_count == 0 ? 'closed' : d.daily_count) }); }
edit: attempt use .merge() , .each() create , update chart. can't figure out how update dynamically each bar div contains 2 child divs display data. still doesn't work dynamically, although renders above:
this.render = function(self){ if(self.data){ self.x = d3.scalelinear() .domain([0, d3.max(self.data.map(function(d) { return parseint(d.daily_count); })) ]) .range([0, 500]); var chart = d3.select("#chart"); var bars = chart.selectall("d") .data(self.data) bars.enter().append('div') .attr('class', 'bar-container row') .each(function(d) { d3.select(this).append('div') .attr('class', 'label 4 columns'); d3.select(this).append('div') .attr('class', 'bar 8 columns'); }) .merge(bars) .each(function(d){ d3.select(this).selectall('div.label') .text(function(d) {return d.date_string; }); d3.select(this).selectall('div.bar') .style('background-color', function(d){ return (d.daily_count == 0 ? 'white' : '#1eaedb') }) .style('color', function(d){ return (d.daily_count == 0 ? 'red' : 'white') }) .style("width", function(d) { return self.x(d.daily_count) + "px"; }) .text(function(d) { return (d.daily_count == 0 ? 'closed' : d.daily_count) }); }) bars.exit().remove();
your render
function needs proper "enter", "update" , "exit" selections. besides that, have in mind bostock's example linked uses d3 version 3.x, while you're using d3 version 4.x (see here how set selections in d3 v4.x).
in following demo, binds data:
var bars = body.selectall("div") .data(data);
after that, "enter" + "update" selections, merge
:
bars.enter().append("div") .attr("class", "row") .merge(bars) .style('background-color', function(d){ return (d.daily_count == 0 ? 'white' : '#1eaedb') }) .style('color', function(d){ return (d.daily_count == 0 ? 'red' : 'white') }) .style("width", function(d) { return x(d.daily_count) + "px"; }) .text(function(d) { return (d.daily_count == 0 ? 'closed' : d.daily_count) });
and exit selection:
bars.exit().remove();
this demo based on code (using daily_count
, because don't know how positioning other divs):
var dataset = [{daily_count: 19}, {daily_count: 29}, {daily_count: 13}, {daily_count: 45}, {daily_count: 22}, {daily_count: 42}, {daily_count: 9}]; render(dataset) d3.select("#btn").on("click", function(){ var newdataset = []; var length = math.ceil(math.random()*20); for (var = 0; < length; i++){ newdataset.push({daily_count: math.floor(math.random()*50)}) } render(newdataset); }) function render(data){ x = d3.scalelinear() .domain([0, d3.max(data.map(function(d) { return parseint(d.daily_count); })) ]) .range([0, 300]); var body = d3.select("body"); var bars = body.selectall("div") .data(data); bars.enter().append("div") .attr("class", "row") .merge(bars) .style('background-color', function(d){ return (d.daily_count == 0 ? 'white' : '#1eaedb') }) .style('color', function(d){ return (d.daily_count == 0 ? 'red' : 'white') }) .style("width", function(d) { return x(d.daily_count) + "px"; }) .text(function(d) { return (d.daily_count == 0 ? 'closed' : d.daily_count) }); bars.exit().remove(); }
.row { font: 10px sans-serif; text-align: right; padding: 3px; margin: 2px; color: white; }
<script src="https://d3js.org/d3.v4.min.js"></script> <button id="btn">click</button>
Comments
Post a Comment