I'm practicing a challenge of making an order checkout page. And I have made a few payment options using the radio button. The text content inside will be visible only if I click on it. But when I click on the radio button it doesn't show the content inside it and shows the "Cannot read property 'classList' of undefined" error.
Here is the Javascript code:
var Input = document.querySelectorAll("input[name='method']");
var show = document.querySelectorAll(".on");
for(var i = 0, max = Input.length; i < max; i++) {
Input[i].onclick = function() {
show[i].classList.add("visible");
show[i].classList.remove("hide");
}
}
Here is a link to my codepen for HTML and CSS code:
Top comments (3)
Hi @sanketnjain5 !
You have discovered a hard-to-find bug! π
I will tell you my recommended solutions now, but please read on to understand why they work:
Option 1: Use let instead of var
Option 2: Copy
i
into a new variable inside your loop to save its current valueI believe the root of your problem lies in a misunderstanding of how variable scope and variables declared with var work. Let me try to illustrate with a simpler example. π
When you create a function that references a variable defined outside the function, it creates what we call a "closure". You can imagine the variable is a box, and the function is closing its little hands around that box.
But it is important to remember: the function is not holding onto what is inside the box, it is simply holding onto the box. If someone reaches into the box and replaces the contents, your function is still holding the box, but the next time it reaches inside it, it'll pull out something different.
Now, going back to what is happening in your code.
You can imagine that the loop you have written:
Can be rewritten like this:
This code, in turn, can be rewritten as:
What you should notice is that your function is holding onto your
i
box, and every time you change the contents of youri
box, it impacts your function. Remember, your function is not holding onto what's inside thei
box, but rather thei
box itself.This means that whenever your function is called, it will use whatever the
i
box has inside it at that moment.If you add a
console.log
statement to your function, you can see exactly what thei
box has inside it when your function is called:Once you add that and start clicking on your buttons, you will see that
i
always contains the same value, regardless of which button you click! The reason is simple: you gave each button a handle to thei
box, not what was inside it. That's probably not what you meant to do.That is the first factor contributing to your error. But that's not all: the value contained by your
i
box when you click on a button is larger than the number of items in your list, and this is the second factor of your error. Why does this happen?The reason this happens is because of how you are changing the contents of your
i
box in the context of yourfor
loop: you are usingi++
, which says "increment the value ofi
after this round of the loop." If you think about it, that meansi
will always be exactly 1 + the length of your list, after your loop is finished.Combine that with the fact that your
onclick
functions always use the latest value ofi
, and congratulations: you have an error!Thanks man!! For finding such a hard errorπ πππ
Hi!!
Thank you for spending your time to solve my question. As I'm new to javascript so can you explain what "const type = event.target.dataset.methodType;" does?