0

I have many these links in my template

<a href="javascript:void(0);" class="add_to_cart" data-slug="{{ product.slug }}">Add</a>

And need click to the link and get certain data-slug. I try use JS and get all links so.

var add_to_cart = document.getElementsByClassName('add_to_cart');

After I try for

for(var i = 0; i < add_to_cart.length; i++) {
    product_slug = add_to_cart[i].getAttribute('data-slug')

    add_to_cart[i].onclick = function() {
        console.log(product_slug)
    }
}

And after click always console.log have last data-slug latest link in my template. How to fix it and get the data-slug of the item I clicked on. Help me, please.

  • 2
    This is unrelated to the question at hand, but it's generally considered best practice to _not_ use anchor tags without an actual href attribute. If you don't actually want to take the user somewhere, it's probably better to use a ` – Chris Hall May 08 '19 at 17:51
  • 1
    @ChrisHall exactly. Doing it that way is un-semantic. – Alexander Lallier May 08 '19 at 18:33
  • @ChrisHall, okey, thanks) –  May 09 '19 at 14:14

3 Answers3

0

Your for loop does not work because the value of product_slug is set when the loop runs. Because product_slug is a var you overwrite it each time the loop runs. And when the click listener is called product_slug will have the same value it had when the loop ran for the last time.

var creates a variable with function scope, it is defined in the scope of the function.

let or const creates a variable with block scope, it is defined in the scope of the block (inside the curly braces { }).

Read more about scope.

So you want to use let.

for(var i = 0; i < add_to_cart.length; i++) {
    let product_slug = add_to_cart[i].getAttribute('data-slug')
    add_to_cart[i].onclick = function() {
        console.log(product_slug)
    }
}
Wendelin
  • 2,354
  • 1
  • 11
  • 28
0

You want to use the target of the click. That's the .target attribute of the first argument to the event handler.

For example, the following code assigns an event handler to all the add_to_cart elements on the page and logs the slug to the console when they're clicked:

let add_to_cart_buttons = document.querySelectorAll('.add_to_cart');

add_to_cart_buttons.forEach(function(node) {
  node.addEventListener('click', (e) => console.log(e.target.dataset.slug));
});

EDIT: Apologies, I misread your second code block when I first wrote this. Your use of document.getElementsByClassName is correct.

Chris Hall
  • 875
  • 10
  • 18
0

You are defining a variable that is written n times during a for loop, and n events that will display the value. That's why you have the same output each time.

What you can do is get the current target of your onclick event, and then display it's data-slug attribute

your for loop would look like this :

var add_to_cart = document.getElementsByClassName('add_to_cart');
for(var i = 0; i < add_to_cart.length; i++) {

    add_to_cart[i].onclick = function(evt) {
        console.log(evt.target.getAttribute('data-slug'));
    }
}
Dimitri Mockelyn
  • 1,535
  • 2
  • 11
  • 17