0

I'm hoping someone could help me figure out why at the first console.log (searchButton.textContent) I'm getting the correct values of the buttons but once I add an event-listener it only shows the last button dataset attribute. I tried to put the code (event listener) inside the first bracket but then it prints out last button dataset for every button I click. I'm learning Javascript and still quite new, thanks in advance!

// Dynamically craete buttons for previous searches
createButtons();
function createButtons (){
  var dropdownHistory = JSON.parse(localStorage.getItem('searchHistory'));
  var searchButtons = document.querySelector('.search-buttons');

  for (var i = 0; i < dropdownHistory.length; i++){
    var searchButton = document.createElement('button');
    searchButton.textContent = dropdownHistory[i];
    searchButtons.appendChild(searchButton);
    searchButton.setAttribute('data-name', dropdownHistory[i])
    console.log(searchButton.textContent);
    }
    searchButton.addEventListener('click', function(event){
      event.preventDefault();
      console.log(searchButton.dataset.name)
    })
    
    }

I've tried moving event listener outside of the different brackets but still doesn't work as intended

Val
  • 21
  • 2

1 Answers1

0

That's a classic closure pitfall. Closures hold onto variable references, they aren't copying values. Therefore searchButton is the same variable in all listeners.

The easiest way to solve that is to create a listener factory outside the loop.

e.g.

 for (var i = 0; i < dropdownHistory.length; i++){
    var searchButton = document.createElement('button');
    searchButton.addEventListener('click', clickListenerFor(searchButton));
 }


function clickListenerFor(button) {
    return function (e) {
         //use button here
    };
}

Alternatively you could reference the button with event.currentTarget which returns the object onto which the listener has been attached to.

From a design perspective it would probably be better to encapsulate the whole button creation process (e.g. createSearchButton(text, name) as a cohesive unit rather than just the listener, which would indirectly solve the problem as there wouldn't be loops in that context.

plalx
  • 42,889
  • 6
  • 74
  • 90
  • Thank you so much for your help! I followed your instructions and it worked. Sorry, just a quick question what does 'return function (e)' does in this case? – Val Jan 01 '23 at 22:56