简体   繁体   中英

Unable to filter using html input value in D3JS

Would like to know if I could use two html input elements can be used to filter out d.rating and d.value(see code below).Also could I replace the csv dynamically if I use a dropdown and allow the user to select which csv they want to see the visualization for.

https://plnkr.co/edit/WgGs5bcHUP3AmjncivPM?p=preview

 <html> <head> <!-- Mobile Specific Metas –––––––––––––––––––––––––––––––––––––––––––––––––– --> <meta name="viewport" content="width=device-width, initial-scale=1"> </head> <body> <input id="myInput" type="number"> <div class="container"> <svg width="1250" height="1080"></svg> <script src="https://d3js.org/d3.v4.min.js"></script> <script> var svg = d3.select("svg"), width = +svg.attr("width"); var format = d3.format(",d"); var color = d3.scaleOrdinal(d3.schemeCategory10); var pack = d3.pack() .size([width, width]) .padding(1.5); var myInput; d3.select("#myInput").on("change", function(){ myInput = this.value; d3.csv("austin_fsq.csv", function(d) { d.sno = +d.sno; if (d.sno && d.rating>=9&&d.value < myInput) return d; }, function(error, classes) { if (error) throw error; var root = d3.hierarchy({children: classes}) .sum(function(d) { return d.value; }) .each(function(d) { if (id = d.data.id) { var id, i = id.lastIndexOf("."); d.id = id; d.package = id.slice(0, i); d.class = id.slice(i + 1); } }); var node = svg.selectAll(".node") .data(pack(root).leaves()) .enter().append("g") .attr("class", "node") .attr("transform", function(d) { return "translate(" + dx + "," + dy + ")"; }); node.append("circle") .attr("id", function(d) { return d.id; }) .attr("r", function(d) { return dr; }) .style("fill", function(d) { return color(d.package); }); node.append("clipPath") .attr("id", function(d) { return "clip-" + d.id; }) .append("use") .attr("xlink:href", function(d) { return "#" + d.id; }); node.append("text") .attr("clip-path", function(d) { return "url(#clip-" + d.id + ")"; }) .selectAll("tspan") .data(function(d) { return d.class.split(/(?=[AZ][^AZ])/g); }) .enter().append("tspan") .attr("x", 0) .attr("y", function(d, i, nodes) { return 13 + (i - nodes.length / 2 - 0.5) * 10; }) .text(function(d) { return d; }); node.append("title") .text(function(d) { return d.data.id + "\\n" + format(d.value); }); }); }) </script> </div> </html> 

You have to convert the input value to a number before using it in the if condition (with the unary operator plus, for instance):

if (d.sno && d.rating >= 9 && d.value < +myInput) return d;
    //converting to a number -----------^

Here is your updated plunker: https://plnkr.co/edit/wmFIxN6ZydAxLhVDSWNf?p=preview

EDIT : avoinding using the row function.

Right now, you're using the row function to filter your data. This has the unwanted effect of loading and parsing the CSV file after the input being entered, which can lead to some delay (never a good user experience).

An alternative is filtering the data after loading and parsing it. This is the logic:

//d3.csv loads and parses the CSV file
d3.csv("austin_fsq.csv", function(d) {
    d.sno = +d.sno;
    return d;
}, function(error, data) {
    if (error) throw error;

    //check the input inside d3.csv
    d3.select("#myInput").on("change", function() {
        myInput = this.value;
        var classes = data.filter(d => d.value < myInput && d.rating >= 9);
        //on change, call a function to draw the results
        draw(classes);
    });

    //the function to draw the results here
    function draw(classes) {
        //code here...
    }
});

Actually, if you use this approach, you can easily solve the second problem in your question, which is getting both input values:

var inputs = {};

d3.selectAll("input").on("change", function() {
    inputs[this.id] = +this.value;
    if (inputs.myValue && inputs.myRating) {
        var classes = data.filter(d => d.value < inputs.myValue && d.rating >= inputs.myRating);
        draw(classes);
    }
})

Here is the plunker showing it, you can set both values and you can see that there is almost no delay after you hit "enter" for the second one: https://plnkr.co/edit/AjVBK3rTOF5aI4eDDbV5?p=preview

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM