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