Suppose I have a group of buttons, each of which assigns a different color to a clicked element. So, red button makes the clicked element turn red.
Rather than write out an event handler for each one, I'd like to write one dynamically named event handler.
So far, I have tried creating an array of color names:
const colors = ['red', 'orange', 'yellow', ...]
then looping through that array:
for (i = 0; i < colors.length; i ) {
// for each color in array, assign it to a button
colors[i].addEventListener("click", function () {
...
});
}
Hoping that I would end up with red.addEventListener...
, orange.addEventListener...
etc.
But instead, this results in: TypeError: colors[i].addEventListener is not a function
.
I've tried using template literals without success. This seemed promising, but didn't work (possibly because I'm not sure I fully understand what's going on there).
Thanks in advance, and let me know if I can clarify.
CodePudding user response:
This suggests that you need to integrate your HTML with your JS.
<!-- HTML -->
<button id="pink">Pink</button>
<button id="yellow">Yellow</button>
<button id="cyan">Cyan</button>
<!-- JS -->
// add EventListener to each .color-button
[].slice(document.getElementsByClassName("color-button")).forEach(button => {
button.addEventListener("click", buttonHandler, !1)
});
// use the id-attribute of each button to
// set the button's background colour
const = buttonHandler = (e) => {
let target = e.target,
color = target.id;
target.style.bacgroundColor = color;
};
CodePudding user response:
You can programmatically create the buttons and/or add an eventlistener like so:
const buttonContainer = document.getElementById('button-container');
const target = document.getElementById('target');
const colors = [ "red", "blue", "yellow" ];
for (const color of colors) {
const colorButton = document.createElement('button');
colorButton.innerText = color;
colorButton.addEventListener('click', () => {
target.style.backgroundColor = color;
});
buttonContainer.appendChild(colorButton);
}
#target {
width: 200px;
height: 200px;
background-color: red;
}
<div id="button-container"></div>
<div id="target"></div>
You can also add the event listener to an already existing list of buttons, as long as the button identifiers follow a set format:
const target = document.getElementById('target');
const colors = [ "red", "blue", "yellow" ];
for (const color of colors) {
const button = document.getElementById(`button-${color}`);
button.addEventListener('click', () => {
target.style.backgroundColor = color;
});
}
#target {
width: 200px;
height: 200px;
background-color: red;
}
<button id="button-red">red</button>
<button id="button-blue">blue</button>
<button id="button-yellow">yellow</button>
<div id="target"></div>
CodePudding user response:
You can use addEventListener
to an html element, not to a string.
You need to convert your string to and html element to add an event listner to it.
You can create an object with your nodes and assign click event listners to that.
const colors = ['red', 'orange', 'yellow'];
const red = document.getElementById("red");
const orange = document.getElementById("orange");
const yellow = document.getElementById("yellow");
const nodeObj = {
red,
orange,
yellow
}
for (i = 0; i < colors.length; i ) {
// for each color in array, assign it to a button
nodeObj[colors[i]].addEventListener("click", function (e) {
console.log(`You clicked ${e.currentTarget.id}`)
});
}
<p id="red">Red</p>
<p id="orange">Orange</p>
<p id="yellow">Yellow</p>
OR
You can make use of eval
for that (This is a dirty fix).
const colors = ['red', 'orange', 'yellow'];
const red = document.getElementById("red");
const orange = document.getElementById("orange");
const yellow = document.getElementById("yellow");
for (i = 0; i < colors.length; i ) {
// for each color in array, assign it to a button
eval(colors[i]).addEventListener("click", function (e) {
console.log(`You clicked ${e.currentTarget.id}`)
});
}
<p id="red">Red</p>
<p id="orange">Orange</p>
<p id="yellow">Yellow</p>