0

I'm trying to add event listeners to elements in a loop, but I'm struggling with getting the parameter to pass to the anonymous function correctly.

Here's an example of the html that I'm trying to apply the js to:

<button data-messagesend="Hello!">Send Hello</button>
<button data-messagesend="Goodbye!">Send Goodbye</button>

And here's the js:

// sendMsg function that will be applied to elements as an event listener
function sendMsg(msg) {
    console.log(msg);
}

//Get all elements that have the data-sendmessage property
elts=document.querySelectorAll('[data-messagesend]');

//Create global array for messages
var messages=[];

//Loop through elements and add an event listener to call sendMsg with it's massage
for(i=0;i<elts.length;i++) {

    //add element data-sendmessage value to messages array
    messages[i]=elts[i].dataset.messagesend;

    //add event listener
    elts[i].addEventListener('click',function(){sendMsg(messages[i]);}.bind(messages[i]),false);
}

it's the //add event listener line that I'm struggling with

I've also tried:

elts[i].addEventListener('click',function(){sendMsg(messages[i]);}.bind(messages,i),false);

and

elts[i].addEventListener('click',(function(msg){sendMsg(msg);})(messages[i]),false);

But it just returns undefined when the buttons are clicked.

Any help would be great :D

Fiddle

https://jsfiddle.net/to4nLz8L/

Just Lucky Really
  • 1,341
  • 1
  • 15
  • 38

1 Answers1

1

There are a couple of ways to achieve this. The first, answered by @Tushar in the comments (And jFiddle here), which uses the correct way to use enclosure:

// sendMsg function that will be applied to elements as an event listener
function sendMsg(msg) {
    console.log(msg);
}

//Get all elements that have the data-sendmessage property
elts = document.querySelectorAll('[data-messagesend]');

//Create global array for messages
var messages = [];

//Loop through elements and add an event listener to call sendMsg with it's massage
for (i = 0; i < elts.length; i++) {
    (function (i) {
        //add element data-sendmessage value to messages array
        messages[i] = elts[i].dataset.messagesend;
        console.log(messages);
        //add event listener
        elts[i].addEventListener('click', function () {
            sendMsg(messages[i]);
        }, false);
    }(i));
}

And then the second way, referenced by @Barmar for the answer here, which changes the sendMsg function to get the dataset info:

// sendMsg function that will be applied to elements as an event listener
function sendMsg(msg) {
    msg=this.dataset.messagesend||msg;
    console.log(msg);
}

//Get all elements that have the data-sendmessage property
elts=document.querySelectorAll('[data-messagesend]');

//Loop through elements and add an event listener to call sendMsg
for(i=0;i<elts.length;i++) {
    elts[i].addEventListener('click',sendMsg,false);
}

The reason I have preference of the first solution, is that the sendMsg function needs to be changed in the second solution. This would not be possible in all situations, such as using a function from an external js script.

Community
  • 1
  • 1
Just Lucky Really
  • 1,341
  • 1
  • 15
  • 38