jqueryjquery-eventsmutation-observersjquery-on

How to attach dynamically named events to dynamic elements with jQuery


I have elements inside my DOM that contain an attribute called 'data-event'.

It could happen that some of these elements are dynamically added to the DOM, for example after an ajax request.

I'm accessing the element's data-event attribute with jQuery this way, of course:

$('.element-selector').data('event')

event data attribute contains the name of the event to which a function handler must be attached. Let's say this function is called generalHandler().

I can't use .on function directly, cause I don't know the name of the event to which attach the function until I access the element itself, and .on needs the name of the event to be specified first (of course).

$('[data-event]').on('????', generalHandler); 

I could use .each, in order to access each $('[data-event]') and extract the event name and attach the function to it, all from inside the callback function invoked by .each.

Using .each, anyhow, isn't a good solution as well, cause this way I'm not handling all dynamically added $('[data-event]') elements.

I could use DOM element inserted event, attaching it to the body and waiting for [data-event] elements added to the DOM, but I know these events are deprecated. I could extend the MutationObserver object but I don't know anything about performance coding this way.

I'd like to know if there's a way to do what I need using just one instruction/function, maybe using .on in some "magical" way, or something similar. I wouldn't like to use MutationObserver because I should do the "event attachment" operation twice (one for the existing elements and another one for the dynamic ones), I'm not sure how to use it keeping an optimal performance of the page and I don't know exactly how to properly implement it to do just and only what I need (find the event name and attach my handler to it for THAT element).

Any idea?


Solution

  • If I understood you correctly. You want to perform an action based on the event which is provided in the data attribute of the element and these event will be different for each element added. If so, you can try something like this.

    <div class="container">
    
    </div>
    
    $(".container")
    .append("<div data-event='click' class='child'>Click</div>")
    .append('<div data-event="mouseover" class="child">Mouseover</div>')
    .append('<div data-event="mouseout" class="child">Mouseout</div>');
    
    // Listen to all the possible event that can be triggered
    $(".container").on("click mouseover mouseout", ".child", function(e){
    
        // If the required event was triggered for this element then perform the action
        if(e.type === $(this).data("event")){
        console.log("Perform " + e.type);
      } else{
        console.log("Don't Perform " + e.type);
      }
    
    });
    

    Here's a link to JSFiddle