简体   繁体   中英

jquery: how to add event handler to dynamically added element without adding it to existing element again

I'll try to explain my problem: I have a website where the user dynamically adds elements. They all belong to the "toBuy" class. Whenever a new element is added to this class I need to attach a click-handler to only this element but not to all others. To keep my code clean I want to have a function that does this work. Here is what i've tried:

this is how the stuff is added:

$("#addItemButton").click(function(){
            var item= $('#item').val();
            $('#item').val("");
            var quantity= $('#quantity').val();
            $('#quantity').val("");
            var comment=$('#addComment').val();
            $('#addComment').val("");
            //construct new html
            var newitem="<div class='toBuyItem'><div class='item'>";
            newitem+=item;
            newitem+="</div><div class='quantity'>";
            newitem+=quantity; 
            newitem+="</div><div class='comment'><img src='img/comment";
            if(comment==""){
                newitem+="_none"
            }
            newitem+=".png' alt='Comment'></div><div class='itemComment'>"
            newitem+=comment;
            newitem+="</div></div>";

            $("#toBuyItems" ).prepend( newitem );
            toggle("#addItemClicked");
            initializeEventListeners();
        });

then this is the initializeEventListeners function (which I also run when the page loads so that the existing elements have the event handlers already:

function initializeEventListeners(){
        $(".toBuyItem").click(function(){
            console.log($(this).html());
            console.log($(this).has('.itemComment').length);
            if($(this).has('.itemComment').length != 0){
                console.log("toggling");
                $(this).addClass("toggling");
                toggle(".toggling .itemComment");
                $(this).removeClass("toggling");
            }          
        });
    }
function toggle(item){

        $( item ).slideToggle(500);
    }

now apparently what happens is that when a new element is added the existing elements get a new event handler for clicking (so they have it twice). Meaning that they toggle on and off with just one click. Probably it's damn simple but I cannot wrap my head around it....

EDIT: so this works:

$(document).on('click', '.toBuyItem', function(){
    if($(this).has('.itemComment').length != 0){
        console.log("toggling");
        $(this).addClass("toggling");
        toggle(".toggling .itemComment");
        $(this).removeClass("toggling");
    } 


    });

Use jquery's on method. This way you have to add event only once. This will be added automatically to dynamically added elements.

$(document/parentSelector).on('click', '.toBuyItem', function() {
    // Event handler code here
});

If you are using parentSelector in the above syntax, it has to be present at the time of adding event.

Docs: https://api.jquery.com/on

You can use jQuery.on method . It can attach handlers to all existing in the DOM and created in future tags of the selector. Syntax is as follows:

$(document).on('click', '.toBuyItem', function(){
//do onClick stuff
})

As others have suggested, you can delegate click handling to document or some suitable container element, and that's probably what I would do.

But you could alternatively define a named click handler, which would be available to be attached to elements already present on page load, and (scope permitting) to elements added later.

You might choose to write ...

function buy() {
    if($(this).has('.itemComment').length != 0) {
        $(this).addClass("toggling");
        toggle(".toggling .itemComment");
        $(this).removeClass("toggling");
    }
}
function initializeEventListeners() {
    $(".toBuyItem").on('click', buy);
}
$("#addItemButton").on('click', function() {
    var item = $('#item').val(),
        quantity = $('#quantity').val(),
        comment = $('#addComment').val();
    $('#item', '#quantity', '#addComment').val("");
    //construct and append a new item
    var $newitem = $('<div class="toBuyItem"><div class="item">' + item + '</div><div class="quantity">' + quantity + '</div><div class="comment"><img alt="Comment"></div><div class="itemComment">' + comment + '</div></div>').prependTo("#toBuyItems").on('click', buy);// <<<<< here, you benefit from having named the click handler
    $newitem.find(".comment img").attr('src', comment ? 'img/comment.png' : 'img/comment_none.png');
    toggle("#addItemClicked");
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM