Younghun Jung
Younghun Jung

Reputation: 361

How can I delegate 'change' event on input element from body?

I know already about event delegation by jQuery. However, How can I do same thing with pure Javascript without jQuery.

Although I attached change event on body or the top element(div), change event is not triggered when value of input element in body or top element is changed...

How can I do this?

Upvotes: 4

Views: 4164

Answers (3)

Kostas Minaidis
Kostas Minaidis

Reputation: 5412

Tl;DR: you probably need to listen on the input event instead.


The reason you are probably not seeing the event being triggered, is because it is triggered: "...when the element loses focus after its value was changed." Source: MDN.

What you probably need to listen to, is the input event instead which "fires when the value has been changed." Source: MDN

Here's an event listener attached to the <body> HTML element which captures all the 'bubbled' input and change events (see how the input event is triggered immediately whereas the change event requires that the input element loses focus, e.g. when pressing Tab):

<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Input Event Delegation</title>
  </head>
  <body>
    <input name="email" type="email" />
    <input name="name" type="text" />
    <script>
      document.body.addEventListener("input", (e) => {
        console.log("type:", e.type, "value:", e.target.value);
      });
      document.body.addEventListener("change", (e) => {
        console.log("type:", e.type, "value:", e.target.value);
      });
    </script>
  </body>
</html>

Upvotes: 0

Luca Kiebel
Luca Kiebel

Reputation: 10096

You can just listen for the event on one element (in this case elSelector) and then only execute the event when the actual target fits a selector in that element.

function on(elSelector, eventName, selector, fn) {
    var element = document.querySelector(elSelector);

    element.addEventListener(eventName, function(event) {
        var possibleTargets = element.querySelectorAll(selector);
        var target = event.target;

        for (var i = 0, l = possibleTargets.length; i < l; i++) {
            var el = target;
            var p = possibleTargets[i];

            while(el && el !== element) {
                if (el === p) {
                    return fn.call(p, event);
                }

                el = el.parentNode;
            }
        }
    });
}

In the example below you can see that it also works with dynamic elements!

on("#inputs", "change", ".event", (target, evt) => console.log(target.target));




function on(elSelector, eventName, selector, fn) {
  var element = document.querySelector(elSelector);

  element.addEventListener(eventName, function(event) {
    var possibleTargets = element.querySelectorAll(selector);
    var target = event.target;

    for (var i = 0, l = possibleTargets.length; i < l; i++) {
      var el = target;
      var p = possibleTargets[i];

      while (el && el !== element) {
        if (el === p) {
          return fn.call(p, event);
        }

        el = el.parentNode;
      }
    }
  });
}

/** random code for the button to add more inputs **/

let i = 7;

document.querySelector("#b").addEventListener("click", () => {
  document.querySelector("#inputs").innerHTML += i + ` <input type="text" class="event"> <br>`;
  i++;
});
<div id="inputs">
  1 <input type="text" class="event"> <br>
  2 <input type="text" class=""> <br>
  3 <input type="text" class="event"> <br>
  4 <input type="text" class=""> <br>
  5 <input type="text" class="event"> <br>
  6 <input type="text" class=""> <br>
</div>

<br><br>
<button id="b">Add another input</button>

Upvotes: 1

Lajos Arpad
Lajos Arpad

Reputation: 76464

Let's define your event function:

function(event) doSomething{
    //Your code
}

Let's get all the input tags inside your body:

var inputs = document.getElementsByTagName('input');

Now, let's iterate them and attach the event:

for (var inputIndex = 0; inputIndex < inputs.length; inputIndex++) {
    inputs.addEventListener('change', doSomething);
}

Upvotes: 0

Related Questions