2
\$\begingroup\$

In this chart I'm calling d3.csv everytime I update the data, which if I understand correctly is a bad thing to do.

In this answer on S.O the answerer explains that d3.csv is asynchronous and the data should only be loaded in once.

I understand why that is, but what I'm wondering now is what is a better way of doing this and if the way that I've done it in the sample code is ever acceptable.

<html>
<head>
<meta charset ="utf-8">
<script src="//d3js.org/d3.v4.min.js"></script>

<style>

body {
    margin:auto;
    width:850px;
    font:10px arial;
    padding:25px;
    color:#555;
}
select {
    border: none;
    border-bottom: 1px solid #ccc;
    padding: 3px;
    text-decoration: none;
    font-size: 11px;
    cursor: pointer;
}
select:focus {
    outline:0;
}
.sortCheck {
    float:right;
    margin-top:-35px;
    margin-right:190px;
}
#myCheckbox {
    position:relative;
    top:3px;
}

/* --- Chart Css --- */
.barEnter {
    fill: steelblue;
    opacity: .9;
}
.barEnter:hover {
    opacity: 1;
}
.axis--x path {
    display: none;
}
.grid--y path,
.grid--y text {
    display: none;
}
.grid--y line {
    opacity:.15;
}

</style>

</head>

<body onclick>

<h2 style="font-weight:lighter;">Mulitple datasets test</h2>

<!-- Selection Category -->
<b style="font-size:11px;">
Choose Category
</b>

<select id="category">
    <option value=" 1">Category 1</option>
    <option value=" 2">Category 2</option>
</select> 

<!-- Selection New dataset -->
<span style="margin-left:30px;">
<b style="font-size:11px;">
Choose Year
</b>

<select id="year" onchange="toggle();">
    <option value="data2017">2017</option>
    <option value="data2016">2016</option>
</select>

</span>

<!-- Chart -->
<div id="chart"></div>

<!-- Sort dimension -->
<span class="sortCheck">Sort Values
<input type="checkbox" id="myCheckbox">
</span>

<script>

let Globalvar = {}; // Global access variables

Globalvar.csvShift = "data.csv"; // CSV init

let formatValue = d3.format(",.0f");

let margin = {top: 35, right: 145, bottom: 35, left: 45},
    width = 700 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

let x = d3.scaleBand().rangeRound([0, width]).padding(0.1),
    y = d3.scaleLinear().rangeRound([height, 0]);

let xAxis = d3.axisBottom(x),
    yAxis = d3.axisLeft(y),
    yGrid = d3.axisLeft(y).tickSize(-width);

let g = d3.select("#chart").append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform","translate(" + margin.left + "," + margin.top + ")");

let sideTextX = width + 30,
    sideTextY = -height + height;

Globalvar.durations = 0;

function afterLoad() {
    Globalvar.durations = 750;
};
// Sum of value
g.append("text")
    .attr("fill","#555")
    .attr("font-weight","bold")
    .attr("font-size",11)
    .attr("x", sideTextX)
    .attr("y", sideTextY)
    .text("Accumulated value: ")
g.append("text").attr("id","totalValue")
    .attr("fill","#555")
    .attr("font-size",11)
    .attr("x", sideTextX)
    .attr("y", sideTextY + 20);
// Average value
g.append("text")
    .attr("fill","#555")
    .attr("font-weight","bold")
    .attr("font-size",11)
    .attr("x", sideTextX)
    .attr("y", sideTextY + 40)
    .text("Average value: ")
g.append("text").attr("id","avgValue")
    .attr("fill","#555")
    .attr("font-size",11)
    .attr("x", sideTextX)
    .attr("y", sideTextY + 60);

g.append("g")
    .attr("class", "axis axis--x")
    .attr("transform", "translate(0," + height + ")");

g.append("g")
    .attr("class", "axis axis--y");

g.append("g")
    .attr("class", "axis grid--y");

// event handlers
d3.select("#myCheckbox").on('change', update);
d3.select("#category").on('change', update);

update();

var file, catInt;

function update() {

  file = Globalvar.csvShift
  catInt = d3.select('#category').property('value');

    d3.csv(file, type, function(error,data) {

        if(error) throw error;

        var sortIndex = data.map(function(d){ return d.month});

        // Update domain
        y.domain([0, d3.max(data, function(d) {
                return d["Category" + catInt]; })
        ]).nice();

        // Update axis
        g.selectAll(".axis.axis--y").transition()
            .duration(Globalvar.durations)
            .call(yAxis);
        g.selectAll(".axis.grid--y").transition()
            .duration(Globalvar.durations)
            .call(yGrid);

        // Sums and averages
        let sumOfAll = d3.sum(data, function(d) {
            return d["Category" + catInt];
        });
        let avgValue = d3.sum(data, function(d) {
            return d["Category" + catInt];
        }) / data.length;

        //sort data
        data.sort( d3.select("#myCheckbox").property("checked")
            ? function(a, b) { return b["Category" + catInt] - a["Category" + catInt]; }
            : function(a, b) { return sortIndex.indexOf(a.month) - sortIndex.indexOf(b.month);})

        // set x domain
        x.domain(data.map(function(d) { return d.month; }));

        g.selectAll(".axis.axis--x").transition()
        .duration(Globalvar.durations)
        .call(xAxis);

        // Update rectangles
        let bars = g.selectAll(".barEnter")
          .data(data, function(d){
            return d.month;
          });

        bars = bars
          .enter()
          .append("rect")
        .attr("class", "barEnter") // Enter data reference
        .attr("width", x.bandwidth())
        .merge(bars);

        bars.transition()
            .duration(Globalvar.durations)
            .attr("height", function(d) { 
                return height - y(d["Category" + catInt]); 
                })
            .attr("x", function(d) { 
            return x(d.month); 
        })
            .attr("y", function(d) { 
                return y(d["Category" + catInt]); 
                });

    bars.exit().remove();

        // Update text on rectangles
        let textUpdate = g.selectAll(".textEnter")
          .data(data, function(d){
            return d.month;
          });

        textUpdate = textUpdate.enter()
        .append("text")
        .style("text-shadow","1px 1px #777")
        .attr("class", "textEnter") // Enter data reference
        .attr("text-anchor","middle")
        .attr("font-size",11)
        .attr("fill","#fff")
        .merge(textUpdate);

        textUpdate.transition()
            .duration(Globalvar.durations)
            .attr("y", function(d) { 
                return y(d["Category" + catInt]) + 15; 
                })
            // Update text value
            .text( function(d) { 
                return d["Category" + catInt]; 
            })
            .attr("x", function(d) { 
            return x(d.month) + x.bandwidth()/2; 
        })

        // Update sum and avg value
        g.selectAll("#totalValue").transition()
            .duration(Globalvar.durations)
            .text(sumOfAll + " Category " + catInt)
        g.selectAll("#avgValue").transition()
            .duration(Globalvar.durations)
            .text(formatValue(avgValue))

        afterLoad()
    });
} 

// Initialize csv data
function type(d) {
    d["Category" + catInt] = +d["Category" + catInt];
    return d;
}
// Toggle csv data
function toggle() {
    if (document.getElementById('year').value == 'data2017') {
         Globalvar.csvShift = "data.csv" ;
    } else if 
       (document.getElementById('year').value == 'data2016') {
         Globalvar.csvShift = "data2.csv";
    } update();
}


</script>

</body>
</html> 
\$\endgroup\$
0

1 Answer 1

1
\$\begingroup\$

Well, I am the answerer that gave you that advice on S.O. The reason, or reasons, are actually quite simple.

Right now, every time you change the dropdown menu, you call the update function:

d3.select("#selectbox").on('change', update);

And then, inside update, you have this:

function update() {
    d3.csv("data.csv", function(error, data) {
        //code here
    })
}

Which is not a good design. These are the reasons why:

  1. d3.csv is asynchronous. That means that, every time you call it, it will load the CSV, parse it and run the code inside the callback (while the code outside it keeps running as the CSV is being loaded/parsed). You really should not use d3.csv inside a function called by a change in a dropdown menu. Right now you're not seeing any performance issue because your CSV is not that big. However, if you had a big CSV, or a slow connection, the difference is noticeable.
  2. This is the most important reason: that CSV is the same! Why are you loading it again and again when the user changes the dropdown? It's just an unnecessary waste of resources, which can in certain situations cause a bad user experience.

All that being said, this is the correct design:

d3.csv("data.csv", function(error, data) {
    d3.select("#selectbox").on('change', update);

    function update() {
        //code here
    }
})

Here is your code with that design:

<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
  body {
    font: 10px arial;
    margin: auto;
    position: relative;
    width: 930px;
    padding: 25px;
  }
  
  .line {
    fill: none;
    stroke: #555;
    stroke-width: 1.5px;
  }
  /* === Axis === */
  
  .axis--y .tick:not(.tick--one) line {
    stroke-opacity: .5;
    stroke: #555;
    shape-rendering: crispEdges;
  }
  
  .tick--one line {
    shape-rendering: crispEdges;
  }
  
  .axis--y path {
    display: none;
  }
  /* === Area === */
  
  .area {
    fill-opacity: 0.6;
  }
  
  .area--below {
    fill: darkorange;
  }
  
  .area--above {
    fill: steelblue;
  }
</style>

<body>

  Choose a thing
  <select id="selectbox">
    <option value=" 1">Category 1</option>
    <option value=" 2">Category 2</option>
  </select>

  <div id="chart"></div>

  <script>
    var csv = `date,Category 1,Category 2
20111001,63.4,62.7
20111002,58.0,59.9
20111003,53.3,59.1
20111004,55.7,58.8
20111005,64.2,58.7
20111006,58.8,57.0
20111007,57.9,56.7
20111008,61.8,56.8
20111009,69.3,56.7
20111010,71.2,60.1
20111011,68.7,61.1
20111012,61.8,61.5
20111013,63.0,64.3
20111014,66.9,67.1
20111015,61.7,64.6
20111016,61.8,61.6
20111017,62.8,61.1
20111018,60.8,59.2
20111019,62.1,58.9
20111020,65.1,57.2
20111021,55.6,56.4
20111022,54.4,60.7
20111023,54.4,65.1
20111024,54.8,60.9
20111025,57.9,56.1
20111026,54.6,54.6
20111027,54.4,56.1
20111028,42.5,58.1
20111029,40.9,57.5
20111030,38.6,57.7
20111031,44.2,55.1
20111101,49.6,57.9
20111102,47.2,64.6
20111103,50.1,56.2
20111104,50.1,50.5
20111105,43.5,51.3
20111106,43.8,52.6
20111107,48.9,51.4
20111108,55.5,50.6
20111109,53.7,54.6
20111110,57.7,55.6
20111111,48.5,53.9
20111112,46.8,54.0
20111113,51.1,53.8
20111114,56.8,53.5
20111115,59.7,53.4
20111116,56.5,52.2
20111117,49.6,52.7
20111118,41.5,53.1
20111119,44.3,49.0
20111120,54.0,50.4
20111121,54.1,51.1
20111122,49.4,52.3
20111123,50.0,54.6
20111124,44.0,55.1
20111125,50.3,51.5
20111126,52.1,53.6
20111127,49.6,52.3
20111128,57.2,51.0
20111129,59.1,49.5
20111130,50.6,49.8
20111201,44.3,60.4
20111202,43.9,62.2
20111203,42.1,58.3
20111204,43.9,52.7
20111205,50.2,51.5
20111206,54.2,49.9
20111207,54.6,48.6
20111208,43.4,46.4
20111209,42.2,49.8
20111210,45.0,52.1
20111211,33.8,48.8
20111212,36.8,47.4
20111213,38.6,47.2
20111214,41.9,46.1
20111215,49.6,48.8
20111216,50.2,47.9
20111217,40.6,49.8
20111218,29.1,49.1
20111219,33.7,48.3
20111220,45.8,49.3
20111221,47.4,48.4
20111222,54.4,53.3
20111223,47.8,47.5
20111224,34.9,47.9
20111225,35.9,48.9
20111226,43.6,45.9
20111227,42.9,47.2
20111228,46.2,48.9
20111229,30.8,50.9
20111230,40.8,52.9
20111231,49.8,50.1
20120101,46.3,53.9
20120102,43.2,53.1
20120103,30.3,49.7
20120104,19.2,52.7
20120105,32.1,52.6
20120106,41.2,49.0
20120107,47.0,51.0
20120108,46.0,56.8
20120109,34.7,52.3
20120110,39.4,51.6
20120111,40.4,49.8
20120112,45.4,51.9
20120113,40.7,53.7
20120114,30.4,52.9
20120115,23.9,49.7
20120116,22.6,45.3
20120117,39.8,43.6
20120118,43.2,45.0
20120119,26.3,47.3
20120120,32.8,51.4
20120121,27.4,53.7
20120122,25.0,48.3
20120123,39.4,52.9
20120124,48.7,49.1
20120125,43.0,52.1
20120126,37.1,53.6
20120127,48.2,50.4
20120128,43.7,50.3
20120129,40.1,53.8
20120130,38.0,51.9
20120131,43.5,50.0
20120201,50.4,50.0
20120202,45.8,51.3
20120203,37.5,51.5
20120204,40.8,52.0
20120205,36.5,53.8
20120206,39.1,54.6
20120207,43.2,54.3
20120208,36.5,51.9
20120209,36.5,53.8
20120210,38.3,53.9
20120211,36.9,52.3
20120212,29.7,50.1
20120213,33.1,49.5
20120214,39.6,48.6
20120215,42.3,49.9
20120216,39.7,52.4
20120217,46.0,49.9
20120218,41.2,51.6
20120219,39.8,47.8
20120220,38.1,48.7
20120221,37.1,49.7
20120222,45.5,53.4
20120223,50.6,54.1
20120224,42.7,55.9
20120225,42.6,51.7
20120226,36.9,47.7
20120227,40.9,45.4
20120228,45.9,47.0
20120229,40.7,49.8
20120301,41.3,48.9
20120302,36.8,48.1
20120303,47.6,50.7
20120304,44.2,55.0
20120305,38.5,48.8
20120306,32.9,48.4
20120307,43.3,49.9
20120308,51.2,49.2
20120309,47.8,51.7
20120310,37.2,49.3
20120311,42.9,50.0
20120312,48.8,48.6
20120313,52.6,53.9
20120314,60.5,55.2
20120315,47.2,55.9
20120316,44.7,54.6
20120317,48.2,48.2
20120318,48.2,47.1
20120319,53.1,45.8
20120320,57.8,49.7
20120321,57.5,51.4
20120322,57.3,51.4
20120323,61.7,48.4
20120324,55.8,49.0
20120325,48.4,46.4
20120326,49.8,49.7
20120327,39.6,54.1
20120328,49.7,54.6
20120329,56.8,52.3
20120330,46.5,54.5
20120331,42.2,56.2
20120401,45.3,51.1
20120402,48.1,50.5
20120403,51.2,52.2
20120404,61.0,50.6
20120405,50.7,47.9
20120406,48.0,47.4
20120407,51.1,49.4
20120408,55.7,50.0
20120409,58.3,51.3
20120410,55.0,53.8
20120411,49.0,52.9
20120412,51.7,53.9
20120413,53.1,50.2
20120414,55.2,50.9
20120415,62.3,51.5
20120416,62.9,51.9
20120417,69.3,53.2
20120418,59.0,53.0
20120419,54.1,55.1
20120420,56.5,55.8
20120421,58.2,58.0
20120422,52.4,52.8
20120423,51.6,55.1
20120424,49.3,57.9
20120425,52.5,57.5
20120426,50.5,55.3
20120427,51.9,53.5
20120428,47.4,54.7
20120429,54.1,54.0
20120430,51.9,53.4
20120501,57.4,52.7
20120502,53.7,50.7
20120503,53.1,52.6
20120504,57.2,53.4
20120505,57.0,53.1
20120506,56.6,56.5
20120507,54.6,55.3
20120508,57.9,52.0
20120509,59.2,52.4
20120510,61.1,53.4
20120511,59.7,53.1
20120512,64.1,49.9
20120513,65.3,52.0
20120514,64.2,56.0
20120515,62.0,53.0
20120516,63.8,51.0
20120517,64.5,51.4
20120518,61.0,52.2
20120519,62.6,52.4
20120520,66.2,54.5
20120521,62.7,52.8
20120522,63.7,53.9
20120523,66.4,56.5
20120524,64.5,54.7
20120525,65.4,52.5
20120526,69.4,52.1
20120527,71.9,52.2
20120528,74.4,52.9
20120529,75.9,52.1
20120530,72.9,52.1
20120531,72.5,53.3
20120601,67.2,54.8
20120602,68.3,54.0
20120603,67.7,52.3
20120604,61.9,55.3
20120605,58.3,53.5
20120606,61.7,54.1
20120607,66.7,53.9
20120608,68.7,54.4
20120609,72.2,55.0
20120610,72.6,60.0
20120611,69.2,57.2
20120612,66.9,55.1
20120613,66.7,53.3
20120614,67.7,53.4
20120615,68.5,54.6
20120616,67.5,57.0
20120617,64.2,55.6
20120618,61.7,52.5
20120619,66.4,53.9
20120620,77.9,55.3
20120621,88.3,53.3
20120622,82.2,54.1
20120623,77.0,55.2
20120624,75.4,55.8
20120625,70.9,56.8
20120626,65.9,57.5
20120627,73.5,57.7
20120628,77.4,56.6
20120629,79.6,56.4
20120630,84.2,58.4
20120701,81.8,58.8
20120702,82.5,56.4
20120703,80.2,56.5
20120704,77.8,55.8
20120705,86.1,54.8
20120706,79.9,54.9
20120707,83.5,54.7
20120708,81.5,52.8
20120709,77.8,53.7
20120710,76.1,53.1
20120711,76.3,52.7
20120712,75.8,52.0
20120713,77.2,53.4
20120714,79.3,54.0
20120715,78.9,54.0
20120716,79.6,54.5
20120717,83.3,56.7
20120718,84.3,57.5
20120719,75.1,57.1
20120720,68.4,58.1
20120721,68.4,57.6
20120722,72.2,56.0
20120723,75.6,56.6
20120724,82.6,57.8
20120725,78.4,57.5
20120726,77.0,56.4
20120727,79.4,55.3
20120728,77.4,55.0
20120729,72.5,55.6
20120730,72.9,55.6
20120731,73.6,55.9
20120801,75.0,55.4
20120802,77.7,54.4
20120803,79.7,53.7
20120804,79.6,54.1
20120805,81.5,57.8
20120806,80.0,58.2
20120807,75.7,58.0
20120808,77.8,57.0
20120809,78.6,55.0
20120810,77.8,54.8
20120811,78.5,53.0
20120812,78.8,52.5
20120813,78.6,53.3
20120814,76.8,53.9
20120815,76.7,56.2
20120816,75.9,57.1
20120817,77.6,55.3
20120818,72.6,56.2
20120819,70.4,54.3
20120820,71.8,53.1
20120821,73.6,53.4
20120822,74.7,54.5
20120823,74.6,55.7
20120824,76.0,54.8
20120825,76.2,53.8
20120826,73.4,56.5
20120827,74.6,58.3
20120828,79.4,58.7
20120829,74.7,57.5
20120830,73.5,55.9
20120831,77.9,55.4
20120901,80.7,55.7
20120902,75.1,53.1
20120903,73.5,53.5
20120904,73.5,52.5
20120905,77.7,54.5
20120906,74.2,56.3
20120907,76.0,56.4
20120908,77.1,56.5
20120909,69.7,56.4
20120910,67.8,55.4
20120911,64.0,56.2
20120912,68.1,55.7
20120913,69.3,54.3
20120914,70.0,55.2
20120915,69.3,54.3
20120916,66.3,52.9
20120917,67.0,54.8
20120918,72.8,54.8
20120919,67.2,56.8
20120920,62.1,55.4
20120921,64.0,55.8
20120922,65.5,55.9
20120923,65.7,52.8
20120924,60.4,54.5
20120925,63.2,53.3
20120926,68.5,53.6
20120927,69.2,52.1
20120928,68.7,52.6
20120929,62.5,53.9
20120930,62.3,55.1`;


    var margin = {
        top: 20,
        right: 80,
        bottom: 30,
        left: 45
      },
      width = 960 - margin.left - margin.right,
      height = 400 - margin.top - margin.bottom;

    var parseDate = d3.timeParse("%Y%m%d");

    var formatPercent = d3.format("+.0%"),
      formatValue = d3.format(",.1f"),
      formatChange = function(x) {
        return formatPercent(x - 1);
      };

    var x = d3.scaleTime().range([0, width]),
      y = d3.scaleLinear().range([height, 0])

    var xAxis = d3.axisBottom(x),
      yAxis = d3.axisLeft(y).tickSize(-width, 0).tickFormat(formatChange);

    var line = d3.line()
      .curve(d3.curveCardinal)
      .x(function(d) {
        return x(d.date);
      })
      .y(function(d) {
        return y(d.city);
      });

    var area = d3.area()
      .curve(d3.curveCardinal)
      .x(function(d) {
        return x(d.date);
      })
      .y1(function(d) {
        return y(d.city);
      });

    var g = d3.select("#chart").append("svg")
      .attr("width", width + margin.left + margin.right)
      .attr("height", height + margin.top + margin.bottom)
      .append("g")
      .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

    var gY = g.append("g")
      .attr("class", "axis axis--y");

    g.append("g")
      .attr("class", "axis axis--x")
      .attr("transform", "translate(0," + height + ")")

    var defs = g.append("defs");

    var durations = 0;

    var afterLoad = () => durations = 750;

    var data = d3.csvParse(csv, function(d, _, columns) {
      d.date = parseDate(d.date);
      for (var i = 1, n = columns.length, c; i < n; ++i)
        d[c = columns[i]] = +d[c];
      return d;
    })

    update();

    var VALUE, baseValue;

    function update() {

      d3.selectAll('clipPath').remove();

      VALUE = d3.select('#selectbox').property('value');

      baseValue = data[0]["Category" + VALUE];

      var keys = data.columns.slice(1, 2);

      var copy = [];

      keys.forEach(function(t) {
        t = t.slice(0, -2) // Slice last two letters
        copy.push(t) // Push sliced strings into copy array
      });

      var cities = copy.map(function(id) {
        return {
          id: id,
          values: data.map(function(d) {
            return {
              date: d.date,
              city: d[id + VALUE] / baseValue
            };
          })
        };
      });

      x.domain(d3.extent(data, function(d) {
        return d.date;
      }));

      y.domain([
        d3.min(cities, function(c) {
          return d3.min(c.values, function(d) {
            return d.city;
          });
        }),
        d3.max(cities, function(c) {
          return d3.max(c.values, function(d) {
            return d.city;
          });
        })
      ]).nice();

      area.y0(y(1));

      yAxis.tickValues(d3.scaleLinear()
        .domain(y.domain())
        .ticks(10));

      gY.transition().duration(durations).call(yAxis);

      gY.selectAll(".tick")
        .classed("tick--one", function(d) {
          return Math.abs(d - 1) < 1e-6;
        });

      g.selectAll(".axis.axis--x").transition()
        .duration(durations)
        .call(xAxis);

      defs.append("clipPath")
        .attr("id", "clip-above")
        .append("rect");

      g.selectAll("#clip-above>rect")
        .transition().duration(durations)
        .attr("width", width)
        .attr("height", y(1));

      defs.append("clipPath")
        .attr("id", "clip-below")
        .append("rect");

      g.selectAll("#clip-below>rect")
        .transition().duration(durations)
        .attr("y", y(1))
        .attr("width", width)
        .attr("height", height - y(1));

      // ========= Above Clip =========

      var above = g.selectAll(".above")
        .data(cities);

      above = above
        .enter()
        .append("path")
        .attr("class", "area area--above above")
        .attr("clip-path", "url(#clip-above)")
        .merge(above);

      above.transition()
        .duration(durations)
        .attr("clip-path", "url(#clip-above)")
        .attr("d", function(d) {
          return area(d.values)
        });

      // ========= Below Clip =========

      var below = g.selectAll(".below")
        .data(cities);

      below = below
        .enter()
        .append("path")
        .attr("class", "area area--below below")
        .attr("clip-path", "url(#clip-below)")
        .merge(below);

      below.transition()
        .duration(durations)
        .attr("clip-path", "url(#clip-below)")
        .attr("d", function(d) {
          return area(d.values)
        });

      // ========= Line Path =========

      var cityLine = g.selectAll(".cities")
        .data(cities);

      cityLine = cityLine
        .enter()
        .append("path")
        .attr("class", "line cities")
        .merge(cityLine);

      cityLine.transition()
        .duration(durations)
        .attr("d", function(d) {
          return line(d.values)
        });

      afterLoad();

      d3.select("#selectbox").on('change', update);

    }
  </script>
</body>

PS: as I cant' use d3.csv in the Code Review snippet, I'm using d3.csvParse instead, with the CSV content in a template literal. For completeness, here is the updated Plunker with the pattern I suggested: https://plnkr.co/edit/D9cvHoIw98CJ2xXNPNEj?p=preview

\$\endgroup\$
2
  • \$\begingroup\$ Thank you! What if I have more than one csv file? Should I use something like queue().defer? \$\endgroup\$ Commented Jan 17, 2018 at 13:51
  • 1
    \$\begingroup\$ @RobertAndersson Yes, or you can nest the d3.csv functions, like this: stackoverflow.com/a/41193922/5768908 \$\endgroup\$ Commented Jan 17, 2018 at 13:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.