0

I need some help because I am a little stuck and I'm not sure what I am doing wrong.

I created a table with buttons in each row. I want to give each buttons a unique id. The id will be a JSONObject that I got from calling an API. Here is my code so far:

function display(data){

    var resultdiv = document.getElementById('resultdiv');
    var table = document.createElement('TABLE');
    table.style.margin = "auto";

    var tbody = document.createElement('TBODY');
    table.appendChild(tbody);

        for (var i=0; i<10; i++){

        var store_is = "Closed";
        if (data.businesses[i].is_closed == false){
            store_is = "Open";
        }
        
        var tr = document.createElement('TR');
        var td1 = document.createElement('TD');
        var td2 = document.createElement('TD');
        var td3 = document.createElement('TD');
        var td4 = document.createElement('TD');

        var img = document.createElement("img");
        img.src = data.businesses[i].image_url;
        img.style.width = "100px";
        img.style.height="100px";

        var btn = document.createElement('button');
        btn.innerHTML = "<i class='fas fa-angle-double-right' style='color:#7E3131;'></i>";
        btn.style.borderRadius="8px";
        btn.style.backgroundColor="#F0B27A";
        btn.style.borderColor="#F0B27A";
        btn.style.marginLeft="5px;"
        btn.id = data.businesses[i].id;

        td1.appendChild(img);
        td2.appendChild(document.createTextNode(data.businesses[i].name));
        td3.appendChild(document.createTextNode(store_is));
        td4.appendChild(btn);

        tr.appendChild(td1);
        tr.appendChild(td2);
        tr.appendChild(td3);
        tr.appendChild(td4);
        tbody.appendChild(tr);
   
    }
    resultdiv.appendChild(table);

    
    btn.addEventListener("click" ,function(){

        switch(btn.id){
            case data.businesses[0].id:
                alert(data.businesses[0].name);
                break;
            case data.businesses[1].id:
                alert(data.businesses[1].name);
                break;
            case data.businesses[2].id:
                alert(data.businesses[2].name);
                break;
            case data.businesses[3].id:
                alert(data.businesses[3].name);
                break;
            case data.businesses[4].id:
                alert(data.businesses[4].name);
                break;
            case data.businesses[5].id:
                alert(data.businesses[5].name);
                break;
            case data.businesses[6].id:
                alert(data.businesses[6].name);
                break;
            case data.businesses[7].id:
                alert(data.businesses[7].name);
                break;
            case data.businesses[8].id:
                alert(data.businesses[8].name);
                break;
            case data.businesses[9].id:
                alert(data.businesses[9].name);
                break;
            default:
                alert("Error Sorry");
        }

    })
    
}

Now, I also want to have an EventListener that when I click a button, the id that is assigned to it will alert. The problem I have all the button does not work but only the last button which has the id data.businesses[9].id When I add the event listener inside the loop all buttons work but the alert for all buttons is data.businesses[9].id as well.

Not sure how to make this one work. Any help will be appreciated! Thank you so much in advance!

margaux_xx
  • 23
  • 5
  • 2
    Does this answer your question? [JavaScript closure inside loops – simple practical example](https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) – Elan Hamburger Dec 12 '20 at 16:38
  • Hi @KienHT i am not running it on the browser. I am using yelp's fusion api and it has a cors policy error when run on browser. I am running this on a physical device. So far it runs perfectly and it's not crashing. – margaux_xx Dec 12 '20 at 16:58

1 Answers1

1

Move the event listener for btn inside the for loop, and instead of using var in the for loop, using let like this:

for (let i=0; i<10; i++){

    //your codes

}

As @Elan has mentioned, you ran into the problem with closures in Javascript. This is for your reference: https://www.w3schools.com/js/js_function_closures.asp

KienHT
  • 1,098
  • 7
  • 11
  • 2
    @Im_margaux I'd go even further and recommend using `let` exclusively. There is no reason to ever use `var` and using `let` instead will help you avoid these kinds of confusions. – Rocky Sims Dec 12 '20 at 16:58
  • Hi! Thank you for helping! I moved the eventlistener inside and changed my for loop to ```let``` however, the last id ```businesses[9].id``` is still being alrted to all of the buttons. – margaux_xx Dec 12 '20 at 16:59
  • Have you changed `var btn = ...` to `let btn = ...` yet? Replace all the `var`s with `let`s. – Rocky Sims Dec 12 '20 at 17:00
  • 1
    @RockySims Thank you! That worked. I am used to use ```var``` all the time and I never use ```let``` thank you! – margaux_xx Dec 12 '20 at 17:03
  • 2
    @lm_margaux Rocky is right, you should start using `let` instead of `var`. It's a good practice. With hoisting, `var` makes it harder to debug – KienHT Dec 12 '20 at 17:09