Juspeeh
Juspeeh

Reputation: 3

D3.JS how to remove/update

I am reading data from following csv file and filtering the data that I want to be shown using filter with select/option.

opiskelija_id,ryhma_id,opintojakso,laajuus,arvio,arviointipvm
297,1,Asiakkuuksien rakentaminen,5,S,19971216
168,2,Asiakkuuksien rakentaminen,5,S,19981213
167,2,Asiakkuuksien rakentaminen,10,S,19980611
166,2,Asiakkuuksien rakentaminen,15,S,19980603
165,2,Asiakkuuksien rakentaminen,10,S,19981213
164,2,Asiakkuuksien rakentaminen,5,S,19960530
163,2,Asiakkuuksien rakentaminen,5,S,19971215
162,2,Asiakkuuksien rakentaminen,10,S,19970602
161,2,Asiakkuuksien rakentaminen,5,S,19981213
160,2,Asiakkuuksien rakentaminen,5,S,19981213
2,1,Asiakkuuksien rakentaminen,5,S,19981213
1,1,Asiakkuuksien rakentaminen,5,S,19971217
151,3,Asiakkuus,10,S,19950911
150,3,Asiakkuus,10,0,19970828
149,3,Asiakkuus,10,4,19960614
148,3,Asiakkuus,10,4,19960514

I have everything working like intended but removing the elements is giving me trouble. As I choose a new category, new elements pop up but the old elements won't leave even tho I have followed everything on other tutorials and solutions. It updates but won't get rid of the old stuff. Here's the following code (and a demo )I am having trouble with. What am I missing/doing wrong? Help.

function update(){

var change = document.getElementById('test').value;


        //Data
        var circles = svg.selectAll("circle")
            .data(data);                


        //Enter
        circles.enter().append("circle")
                            .attr("r", 0)
                            .attr("cx", function(d) { return xScale(d.arviointipvm); })
                            .attr("cy", function(d, i){return i*15});           


        //Update    
        circles.filter(function(d) { return d.opintojakso == change})
            .attr("fill", function(d){return colorScale(d.arvio)})
            .on("mouseover", function(d){return tooltip.style("visibility", "visible")
                                                    .style("top",(d3.event.pageY-10)+"px")
                                                    .style("left",(d3.event.pageX+10)+"px")
                                                    .html("Opintojakso: " + d.opintojakso 
                                                    +"<br />Arviointipvm: "+d.arviointipvm.getDate()+"."+(d.arviointipvm.getMonth()+1)+"."+d.arviointipvm.getFullYear()
                +"<br /> Arvio: "+d.arvio+"<br /> Opiskelija_Id: "+d.opiskelija_id)})
            .on("mouseout", function(){return tooltip.style("visibility", "hidden");})
            .transition()
            .attr("r", 8);

        //Exit          
        circles.exit().remove();
}

update();

Upvotes: 0

Views: 667

Answers (1)

Mark
Mark

Reputation: 108537

I see a couple issues. First, it looks like you are binding the same data over and over again and then filtering (and making changes) to only those that match your dropdown. Sinces it's the same data again and again, nothing will ever exit. You should probably be filtering the data before binding.

Second, you are not supplying a key function and by default, d3 will use index to compute enter/exit. Your key though should be something unique about each node. With your data, it looks like opiskelija_id fits this bill:

var f_data = data.filter(function(d){
  return (d.opintojakso === change);
});

var circles = svg.selectAll("circle")
  .data(f_data, function(d){
    return d.opiskelija_id;
  }); 

circles.exit().remove();

circles.enter().append( ... ;

A second option here would be to filter as you are doing, but instead hide those that don't match the filter. With this method you would append all the circles up front, hide them all, then filter the circles and make the matching ones visible.

Upvotes: 1

Related Questions