Getting Data from Multiple Buttons on Click

Hello, I'm trying to add an event listener to all buttons within a div, using code such as:
const button= document.querySelectorAll(".percentBtn")

buttons.forEach((btn) => {
btn.addEventListener('click', calculate);
})
const button= document.querySelectorAll(".percentBtn")

buttons.forEach((btn) => {
btn.addEventListener('click', calculate);
})
I then need to be able to get the value of each button depending on click. I call the calculate function (not added here) which will eventually do a calculation based on an input & the value attribute of a button. However, I'm not sure how to get the value attribute of the button clicked. I know I can log all values but running btn.value, but I need to be able to do so on click.
89 Replies
Zoë
Zoë8mo ago
It's probably best to use dataset https://codepen.io/z-/pen/wvRVxrq/7bdc2212715e161c43c68bdda77bf158?editors=1011 unless I have misunderstood you
Matt
Matt8mo ago
Yeha that's what I'm trying to do
ἔρως
ἔρως8mo ago
you mean, just this.value?
Matt
Matt8mo ago
<button class="percent" value="0.05">5%</button>
<button class="percent" value="0.10">10%</button>
<button class="percent" value="0.15">15%</button>
<button class="percent" value="0.25">25%</button>
<button class="percent" value="0.50">50%</button>
<button class="percent" value="0.05">5%</button>
<button class="percent" value="0.10">10%</button>
<button class="percent" value="0.15">15%</button>
<button class="percent" value="0.25">25%</button>
<button class="percent" value="0.50">50%</button>
ἔρως
ἔρως8mo ago
yes, you do mean this.value
Matt
Matt8mo ago
How would I use this in this instamce
ἔρως
ἔρως8mo ago
exactly that line nothing else, nothing more
Matt
Matt8mo ago
const button= document.querySelectorAll(".percentBtn")

buttons.forEach((btn) => {
btn.addEventListener('click', calculate);
})
const button= document.querySelectorAll(".percentBtn")

buttons.forEach((btn) => {
btn.addEventListener('click', calculate);
})
ἔρως
ἔρως8mo ago
no extra code, no framework dependencies ...
Matt
Matt8mo ago
the event listener calls a function
ἔρως
ἔρως8mo ago
just use it inside the calculate function
Matt
Matt8mo ago
how can i get the button that was clicked value?
ἔρως
ἔρως8mo ago
this that's it
Matt
Matt8mo ago
ah so when the function is called, it's automatically associated with the corresponding button
ἔρως
ἔρως8mo ago
or, add a parameter to the function (like e or evt or event) and then usee.target and it's the same-ish as this.value
Matt
Matt8mo ago
when I added parameter, and console.log(parameter.value) it returned undefined
function calculate (button) {
console.log(button.value)
}
function calculate (button) {
console.log(button.value)
}
.this works though
Zoë
Zoë8mo ago
I updated the pen for .value You just want event.target.value
ἔρως
ἔρως8mo ago
instead of this:
function calculate() { ... }
function calculate() { ... }
do this:
function calculate(e) { e.target.value }
function calculate(e) { e.target.value }
or this:
function calculate() { this.value }
function calculate() { this.value }
Matt
Matt8mo ago
Ty 👍 this exactly was my issue didn't add .target, thanks guys for your input
ἔρως
ἔρως8mo ago
a simple trick: just use the long old function syntax and do function(){console.log(arguments);} if you don't know what a function will receive
Matt
Matt8mo ago
This works for what im trying to do
Matt
Matt8mo ago
Frontend Mentor
Frontend Mentor | Tip calculator app coding challenge
This small app is perfect for anyone starting to get to grips with JavaScript. The calculator functionality will be a nice test!
Zoë
Zoë8mo ago
Additionally you can only use this inside of functions without doing anything extra, while arrow functions you have to manually bind it
Matt
Matt8mo ago
I'm almost done with this challenge, was just tripped up with getting button values
ἔρως
ἔρως8mo ago
that looks like a radio input
Matt
Matt8mo ago
Yeah im doing this. I never really used it before but i have read about it. Haven't touch JS in a week or so been pretty busy
ἔρως
ἔρως8mo ago
not a button
Matt
Matt8mo ago
The tip percentage?
ἔρως
ἔρως8mo ago
i would write it with a change event in the form yes
Matt
Matt8mo ago
hm i was writing it with buttons
ἔρως
ἔρως8mo ago
you will cry, trust me on this
Matt
Matt8mo ago
because im assuming once percentage is clicked, it submits calculation why? it doesn't seem too difficult
ἔρως
ἔρως8mo ago
yeah, that's a good way to think about it but then, you have to apply classes to style the elements
Matt
Matt8mo ago
like the active colors when clicked
ἔρως
ἔρως8mo ago
with a radio button, for example, you just style it and use as normal and since you have the change event on the form, you can update imediately
Zoë
Zoë8mo ago
Also as an FYI when you get .value it will be a string and you'll need to parseInt it
Matt
Matt8mo ago
hmm interesting okay will look into tyhis
ἔρως
ἔρως8mo ago
yes, or divide by 1 or add 0, or + in front of it
Matt
Matt8mo ago
thanks for the heads up
ἔρως
ἔρως8mo ago
but in this case, you want parseFloat, because percentages can be floats
Zoë
Zoë8mo ago
Or if you're using the inputs to build up a number like in a calculator leave it as a string until later, it's easier to do that than to multiply by 10 and add
Matt
Matt8mo ago
all value attributes are considered string? because of the quotations?
ἔρως
ἔρως8mo ago
55.5% is valid no it's because they are a "dom string"
Matt
Matt8mo ago
for example <button class="percent" value="0.05">5%</button> is it possible to associate a float value with this button instead of string ? to avoid parsing
ἔρως
ἔρως8mo ago
yes, but it's converted to a string and when you read, it's a string html doesn't have a way to know the data type of an attribute, since everything is a string
Matt
Matt8mo ago
okay that makes sense
Zoë
Zoë8mo ago
On one hand it would be nice if type="number" meant that .value was a number but there's nothing stopping some other code setting the value to something that isn't a number. Additionally users are free to edit the value to anything, so validation has to happen somewhere. You can never trust values to be sensible even if through normal use they should be sensible.
Matt
Matt8mo ago
thats kindve what i assumed tbh
Zoë
Zoë8mo ago
I figured, it's a common assumption and that's why I pointed it out
ἔρως
ἔρως8mo ago
that would be nice but it would open a can of worms, so, i understand it working with dom is something else by the way, .disabled and .checked returns booleans
Zoë
Zoë8mo ago
Even if some browsers enforce only allowing editing of inputs to match set validation there will still be browsers that do allow editing and so you can't rely on it, and returning numbers may cause issues when people assume that they're a string
Matt
Matt8mo ago
Im off pc for a few but gonna rewrite for radio and will probably use this Im assuming radio since only 1 can be checked rather multiple
ἔρως
ἔρως8mo ago
yup you will have so much fun or bash your keyboard
Matt
Matt8mo ago
Lol I gotta go stock my vending machine then I’ll try it out
ἔρως
ἔρως8mo ago
good luck surviving through it this is a very very good point
Zoë
Zoë8mo ago
Even if something like .valueNum was added which stores a number value it still requires checking to see if .valueNum exists and if it doesn't parse .value as a number Matt, be warned that there is bad stuff that is here to stay because for something that is always alive and not everyone is using the latest browsers with the latest features there's a lot of what feels like bodging. We will forever be stuck with .value being a string and it's sad. .dataset came along later and the only time that you get to set things up is at the start and they chose for it to always be a string too, and we're stuck with it for the same reasons 🙃
ἔρως
ἔρως8mo ago
i agree with it being a string, because of sgml or whatever it is called the "base" of xml, html and all these ml thingies and all attributes are strings once given to the element, all data information is lost, and there's no reliable way to pass that information between multiple languages you can just use json, if you need a structure
Matt
Matt8mo ago
Here's my solution where I reworked to use radio 👍 Learned some new things using radio, thanks for suggestion.
ἔρως
ἔρως8mo ago
you're welcome the html needs a ton of improvement you have div > div > div > form > fieldset > label > input this for the radio buttons why not a form for all inputs? and then, for the radio buttons, you can just use a fieldset with a legend, instead of a div with a label and the form then the fieldset... and then, you can just have a change event listener in the form, which will update everything
Matt
Matt8mo ago
Hmm true, I'll post an update shortly
ἔρως
ἔρως8mo ago
it will save you a ton of code and elements
Matt
Matt8mo ago
I did this pretty sloppily, I'm cleaning some stuff up
ἔρως
ἔρως8mo ago
that's fine, just relax
Matt
Matt8mo ago
Here's my re-write. JS was simplied with the form tbh. Thanks for the suggestion
ἔρως
ἔρως8mo ago
you can still cut down 30% of the html and remove the javascript for the reset button instead of <button class="reset">Reset</button> you should do <button type="reset" form="userInput">Reset</button> but you need to change <form class="userInput"> to be an id you then need to add an event listener to the reset event, and change the html to 0.00
Matt
Matt8mo ago
Technically, would the button need to be within form?
ἔρως
ἔρως8mo ago
not if you use the form attribute
Matt
Matt8mo ago
Hmm okay how would you furthur condense the markup? Re-writing the percentages?
ἔρως
ἔρως8mo ago
no, just remove the section and use the form as your section this way, the reset button is inside the form but honestly, worry about fixing your javascript, put an id in the form and then put the form attribute on the button, with type reset
Matt
Matt8mo ago
Thanks and thanks again for your input. You opened my eyes to some different methods for doing things 👍
ἔρως
ἔρως8mo ago
you're welcome remember, if you can do it in pure html, don't do it in javascript
Matt
Matt8mo ago
If I had an input as type="number", does the input eventlistener look for when theres a value change (after pressing enter) or something? Tbh, I tried to do some wacky stuff to change radio button background once checked with JS lol
.percentLabel:has(input[type="radio"]:checked) {
background-color: var(--primary);
}
.percentLabel:has(input[type="radio"]:checked) {
background-color: var(--primary);
}
was so much simplier 😂
ἔρως
ἔρως8mo ago
im not sure what's the difference between change and input, but it's an oportunity to read on it you can do even crazier stuff, like, forcing it to look like a box
Matt
Matt8mo ago
okay just figured I'd ask. The challenge for frontend mentor has a user input where my 50% option is i avoided it for now because i didnt understand the logic but i think i might give it a shot
ἔρως
ἔρως8mo ago
it's fine
Matt
Matt8mo ago
Do you happen to know why visibility: hidden; break the radio buttons, but opacity: 0; is fine?
ἔρως
ἔρως8mo ago
no, but i know that display none does nothing to it
Matt
Matt8mo ago
I'm assuming the correct way is visibility, but cannot seem to figure out why it's breaking
ἔρως
ἔρως8mo ago
it still works oh, wait
Matt
Matt8mo ago
that removes entirely it needs to still be interactive
ἔρως
ἔρως8mo ago
dude, you just put the input in the label, and then the label is what interacts with it you just hide the input after
Matt
Matt8mo ago
yeah thats what i did but im hiding with opacity, not visibility i was curious why visibility doesn't work properly when theoretically it should visibility: hidden should remove visually but not from document
ἔρως
ἔρως8mo ago
ive put display: none on .percentInput and works
Matt
Matt8mo ago
hmm yeah just tried that, didn't think it should because it removes element
ἔρως
ἔρως8mo ago
you assumed, you didn't try try next time worst that will happen is that you did it wrong or there's an easier way
Matt
Matt8mo ago
True well thanks again for feedback, its been helping me learn
ἔρως
ἔρως8mo ago
you're welcome