Applying the same click function to multiple buttons

Hello,

I am trying to write code to apply the same function to multiple buttons. I say the ‘same’ but actually, I want to change the button colour depending on which button is clicked, so the principle is the same, but the ‘event’ is slightly different depending on which button is clicked.

After reading a bit, I came up with following, but it’s not working. Would someone know what I’m doing wrong?

function changeColor() {
  const buttons = document.querySelectorAll(".btn");

  for (let i = 0; i < buttons.length; i++) {
    buttons[i].addEventListener("click", function () {
      buttons[i].style.backgroundColor = "green";
    });
  }

I think missing => and function name in function is causing problem.
@coderostro

please share the html code that comes with this code, it’s needed to help you with debugging. Do you have a codepen or something like that maybe?

as long as the second argument is a function it’s fine, it doesn’t need to be an arrow function

1 Like

thanks, I forgot to change the function name

1 Like

Yes, here it is and thank you (the blue buttons were only coloured to see if I was targeting the right elements in a separate exercise earlier). The code is very rough as I am just practising, so apologies if hard to read.

please explain how to reproduce, and where is the code you are asking about
Or create a different pen with the minimum code necessary to reproduce the issue you are facing

Sorry, I don’t understand. You mean you can’t click on the link I sent to see the code on Codepen?

I can open the pen, I don’t know where to look if you don’t explain

ok, I understand what you mean now.

Having looked at it a second time, I made a few changes and still wrong because I think I’m not sure where I should be trying to change the button background colour within the function either (completely omitted at the moment).

I’ll send the link anyway…

The (incomplete) function is on line 21:

function changePomodoroColor() {
  const pomodoroButtons = document.querySelectorAll(".pomodoro-btn");

  for (let i = 0; i < pomodoroButtons.length; i++) {
    pomodoroButtons[i].addEventListener("click", changePomodoroColor () {
      pomodoroButtons[i].style.backgroundColor = "green";
    });
  }

It really depends on the actual functionality you are going for.

You can use HTML attributes, like ids and data sets. If you make the attribute value the same as the color or class name you can apply it to the click target as inline styles, or using classs.

Example code
<button id="red">Red</button>
<button id="green">Green</button>
<button id="blue">Blue</button>
.red {
  background-color: red;
}

.green {
  background-color: green;
}

.blue {
  background-color: blue;
}
document.querySelectorAll("button").forEach((btn) => {
  btn.addEventListener("click", ({ target }) => {    
    // the id value is the same as the class name
    target.classList.toggle(target.id)
  });
});

thank you. I am sure I am not understanding this code properly though. I have used ‘toggle’ before, but only with the onclick attribute and not with click events (still in the very beginning stages).

I have a few questions about the code if it’s okay…sorry if obvious, but just want to make sure I understand.

Is ‘btn’ in the above just the JS variable I need to declare separately for each individual button? If this is so, would ‘target’ be the same as ‘btn’ in my case?

And in the case of the ‘toggle’ part, how does the function know what to toggle between (what the two alternatives are)?

I think I could do this for one button, it’s the applying the same function to multiple buttons that I’m not sure about.

I tried to do it another way with code I found online, but that’s not working either (codepen attached, code starting at line 46).

I will try your way as soon as I am sure what ‘btn’ and ‘target’ should be.

I basically just want any of the multiple buttons on the right-hand side to turn green if/when clicked.

Just for information, I’ve got it working . I used the following code:

let buttons = document.querySelectorAll(".btn");
for (let i = 0; i < buttons.length; i++) {
  buttons[i].addEventListener("click", function () {
    buttons[i].style.backgroundColor = "green";
  });
}

Isn’t that the same code as in the initial post, minus the function?

How does applying the color green to all the buttons achieve this?

Are you not trying to apply a different color to the buttons depending on how many times they are clicked? Like the tasks’ progress (red, yellow, green).


To answer your questions.

btn is each button element. querySelectorAll returns a NodeList of all the elements. The forEach callback parameter will contain each of the elements.

target is a property on the event object. It is the element that triggered the event (the button clicked). { target } is using object destructuring with the parameter.


You can’t use a single counter for all your buttons.

You could use an HTML dataset attribute to track how many times each button has been clicked.

But if I understand your app, it should be data-driven with an application state. So what is shown on the page is a render of the internal state. Much like a todo app (the curriculum has a todo app tutorial you can look at).

ok, thanks for the explanations.

I don’t want these button to work in the same way as the tasks buttons.

I simply want each individual button to turn green if clicked and to return to the original colour if clicked again.

I have changed this to a toggle function now , because clicking one button was turning all buttons green.

I still haven’t worked out how to get the toggle function working on all buttons though, but I have a separate post on this and just looking at someone’s suggestion to see if I can get it working.

Current code is:

function changeColor() {
  let pomButton1 = document.getElementById("pomodoro-btn-1");
  pomButton1.classList.toggle("colored");
}

it looks like you have multiple topics open on this question, please do not open multiple topics for the same question