Cannot return the value from button

Issue

While console logging I’m getting ‘undefined’. I’m curious to know why I can’t return the value of the buttons. Is the event listener supposed be outside the function ? And also how can to get the value outside the function ?

const buttons = document.querySelectorAll('.rpsButton');
const getPlayerChoice = () => {
  let something = '';
  buttons.forEach(button => {
    button.onclick = e => {
      something = e.target.value;
    }
  })
  return something;
}

console.log(getPlayerChoice());
<div class="buttons">
  <button class="rpsButton" value="Rock">✊</button>
  <button class="rpsButton" value="Paper">🤚</button>
  <button class="rpsButton" value="Scissors">✌</button>
</div>

Solution

At the moment you’re calling a function and, within that, attaching the listeners to the buttons – which is fine, and would make sense if the click handler was just logging the value, but you can’t return a value from that handler, and then the function, like you want to.

So you can do this…

const buttons = document.querySelectorAll('.rpsButton');

const getPlayerChoice = () => {
  buttons.forEach(button => {
    button.onclick = e => {
      console.log(e.target.value);
    }
  });
}

getPlayerChoice();
<div class="buttons">
  <button class="rpsButton" value="Rock">✊</button>
  <button class="rpsButton" value="Paper">🤚</button>
  <button class="rpsButton" value="Scissors">✌</button>
</div>

…but this defeats the purpose of having a specifically-named function that I assume is meant to log the value.

Perhaps what you want to do is to log a value when that function (getPlayerChoice) that has been assigned to a button’s click listener is called.

// Cache the buttons
const buttons = document.querySelectorAll('.rpsButton');

// Add a listener to each button. The listener calls
// the `getPlayerChoice` function when it is fired
buttons.forEach(button => {
  button.addEventListener('click', getPlayerChoice);
});

// Log the value of the clicked element
function getPlayerChoice(e) {
  console.log(e.target.value);
}
<div class="buttons">
  <button class="rpsButton" value="Rock">✊</button>
  <button class="rpsButton" value="Paper">🤚</button>
  <button class="rpsButton" value="Scissors">✌</button>
</div>

A alternative solution would be to attach one listener to the buttons container to catch events from its child elements as they "bubble up" the DOM (aka event delegation). When a click event is fired the listener calls getPlayerChoice. It checks that the element that fired the click event is a button with a rpsButton class, and then logs its value.

// Cache the buttons container, and add _one_ event
// listener to it. Like above the listener calls the
// `getPlayerChoice` function when fired
const buttons = document.querySelector('.buttons');
buttons.addEventListener('click', getPlayerChoice);

// Check that the clicked element has a `rpsButton`
// class, and then log its value
function getPlayerChoice(e) {
  if (e.target.matches('.rpsButton')) {
    console.log(e.target.value);
  }
}
<div class="buttons">
  <button class="rpsButton" value="Rock">✊</button>
  <button class="rpsButton" value="Paper">🤚</button>
  <button class="rpsButton" value="Scissors">✌</button>
</div>

Additional information

Answered By – Andy

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published