Skip to content
Advertisement

d3 getting data binding for selection works but when I iterate the selection, it doesn’t work

I tried to remove the circles having the values of top twenty percents & bottom twenty percents.

So I got the data bound to each element by d3.selectAll().data().

However, once I iterate through the elements, it returns an error message saying selection.data() is not a function why it doesn’t work when I iterate them, while it worked fine when I firstly generated the array?

The code is as below.

function leavingQuarter() {

let years = d3.range(1980, 2022, 1);

years.forEach((t) => {



    let targetYear = d3.selectAll(`.year${t}`);
    let targetYearData = targetYear.data()


    let values = [];
    let twenty;
    let eighty;
    for (let year of targetYearData) {
        values.push(year.wordcount);
    }

    let ascending = values.sort(d3.ascending);
    let numberofEl = ascending.length;
    let twentyper = Math.floor(numberofEl * 0.2);
    let eightyper = Math.floor(numberofEl * 0.8);
    twenty = ascending[twentyper];
    eighty = ascending[eightyper];


    for (let years of targetYear) {

        // Uncaught (in promise) TypeError: years.data is not a function

        if (years.data().wordcount < twenty || years.data().wordcount > eighty) {
            years.transition().duration(500).style('opacity', 0)
        }
    }


})

Advertisement

Answer

I figured out the reason and want to share the reason with someone who is going to have a similar problem oneday.

The solution for this is using selection.each instead.

I solved the problem with the syntax below.

  targetYear.each(function(t) {


        if (d3.select(this).data()[0].wordcount < twenty || d3.select(this).data()[0].wordcount > eighty) {

            d3.select(this).transition().duration(1000).style('opacity', 0)
        }

    })
User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement