0

Currently, I use the following solution:

<button onclick="initiate('ok2')" id="btn1">Initiate</button>
<button id="btn2">Send data</button>
function initiate(ok) {
   document.getElementById("btn2").addEventListener("click", receiveData);
}

function receiveData(event) {
   console.log(event);
}

The benefit of this approach lies in the named function receiveData, which is recognized as the same function and is not added repeatedly.

Steps to reproduce:

  • Press the 'Initiate' button multiple times
  • Press 'Send data'

Result: console log is printed only once

I want to utilize the same approach, but add an attribute to the function. I tried the bind approach, but the event listener is added multiple times. As a result, the console log is also printed multiple times.

Example:

function initiate(ok) {
  document.getElementById("btn2").addEventListener("click", receiveData.bind(null, ok));
}

function receiveData(event, ok) {
  console.log(event);
  console.log(ok);
}

Is it possible to pass an argument to a function and not create duplicate event listeners? Ideally, it would be preferred not to delete event listeners, like in the current solution.

George P.
  • 181
  • 1
  • 8
  • Whats the point of add event listener if you are using on click? – Stefan Avramovic Aug 03 '22 at 18:06
  • 1
    during page initialization, add the event listeneer to btn2 then. instead of on button press? I dont see why you would want to add the listener more than once – Matt Pengelly Aug 03 '22 at 18:08
  • 1
    Why do you need to bind a click in a click? Best solution is to not need to do it. – epascarello Aug 03 '22 at 18:09
  • It is a simplified example. In the problem I am solving, there is communication between iFrame and the parent window using an event listener (window.addEventListener("message", handler)) – George P. Aug 03 '22 at 18:12
  • 2
    Simply use [event delegation](https://stackoverflow.com/q/1687296/215552). rather than binding a new event handler on every click. – Heretic Monkey Aug 03 '22 at 18:20

4 Answers4

1

Here is my version with the recommended ways of delegating and setting and getting data attribute

A user cannot click what is not visible so no need to initiate the button, just unhide it

document.addEventListener("click", function(e) {
  let btn = e.target
  if (btn.matches("#btn1")) {
    let targetBTN = document.getElementById(btn.dataset.target);
    targetBTN.hidden = false;
  } else if (btn.matches("#btn2")) {
    console.log(btn.dataset.field);
  }
});
<button id="btn1" data-target="btn2">Initiate</button>
<button id="btn2" data-field="ok2" hidden>Send data</button>
mplungjan
  • 169,008
  • 28
  • 173
  • 236
0
// when the window loads add a click handler to the button of choice
window.addEventListener('load', (event) => {
  console.log('page is now loaded');
  document.getElementById("btn2").addEventListener("click", receiveData)
});

function receiveData(event) {
  console.log(event);
}

or as suggested in comments, add the click handler inline.

Matt Pengelly
  • 1,480
  • 2
  • 20
  • 34
0

You need to tel it if it is inited or not..

    let data = "";
        let init = true;
        function initiate(ok) {
          
           data = ok
           if(init ){
             document.getElementById("btn2")
             .addEventListener("click", receiveData);
             init = false
            }
        }
        
        function receiveData(event) {
           console.log( data );
        }
<button onclick="initiate('ok2')" id="btn1">Initiate</button>
<button id="btn2">Send data</button>
Stefan Avramovic
  • 1,365
  • 2
  • 11
  • 20
0

It looks like the one goal is to only allow the second button to be able to be used when the first button is clicked.

So, I attached an event listener to the document. Then used data attributes on the buttons to determine if the start button can be used or not. And just for display I used CSS to hide the start button if its not allowed to be used just yet

document.addEventListener("click",function(e){
  let btn = e.target
  if(btn.matches(".btn-start")){
    let targetBTN = document.querySelector(`[data-id='${btn.dataset.target}']`)
    targetBTN.setAttribute("data-initiated","true");
  }
  else if(btn.dataset.initiated == "true"){
    console.log(btn.dataset.field);
  }
});
[data-initiated="false"]{
 display:none
}

[data-initiated="true"]{
 display:inline-block
}
<button data-target="send2" class="btn-start">Initiate</button>
<button data-initiated="false" data-field="ok2" data-id="send2" class="btn-send">Send data</button>
imvain2
  • 15,480
  • 1
  • 16
  • 21