web-dev-qa-db-ja.com

jQuery .on()イベントは、動的に追加された要素に対しては機能しません

私は、ユーザーがボタンをクリックするとボタン付きのdiv全体が動的に挿入されるプロジェクトを作成しています。そのdiv内にはボタンがあり、ユーザーがボタンをクリックすると、たとえば何かに警告するなど、別のことを行います。

問題は、動的に追加されたdivでそのボタンを押しても、何も起こらないことです。イベントはまったく発生しません。

そのdivをHTML内に追加して再試行しましたが、イベントは機能しました。つまり、divが動的に追加されるためだと思います。

追加されたdivにはクラスmainTaskWrapperがあり、ボタンにはクラスcheckButtonがあります。イベントは、以下の_script.js_ファイルの最後に.on()を使用して添付されます。

これが私のコードです:

helper_main_task.js:(divを追加するオブジェクトです。動的に追加されるdivがすべてだと思うので、読む必要はありませんが、念のために入れておきます。必要)

_var MainUtil = {
    tasksArr : [],
    catArr : ["all"],
    add : function(){       

        var MTLabel = $("#mainTaskInput").val(),  //task label  
            MTCategory = $("#mainCatInput").val(), //task category 
            MTPriority = $("#prioritySlider").slider("value"),  //task priority     
            MTContents = $('<div class="wholeTask">\
                                <div class="mainTaskWrapper clearfix">\
                                    <div class="mainMarker"></div>\
                                    <label class="mainTaskLabel"></label>\
                                    <div class="holder"></div>\
                                    <div class="subTrigger"></div>\
                                    <div class="checkButton"></div>\
                                    <div class="optTrigger"></div>\
                                    <div class="addSubButton"></div>\
                                    <div class="mainOptions">\
                                        <ul>\
                                            <li id="mainInfo">Details</li>\
                                            <li id="mainEdit">Edit</li>\
                                            <li id="mainDelete">Delete</li>\
                                        </ul>\
                                    </div>\
                                </div>\
                            </div>');


        this.tasksArr.Push(MTLabel);

        //setting label
        MTContents.find(".mainTaskLabel").text(MTLabel);        

        //setting category  
        if(MTCategory == ""){
            MTCategory = "uncategorized";
        }
        MTContents.attr('data-cat', MTCategory);
        if(this.catArr.indexOf(MTCategory) == -1){
            this.catArr.Push(MTCategory);
            $("#categories ul").append("<li>" + MTCategory +"</li>");
        }
        $("#mainCatInput").autocomplete("option", "source",this.catArr);

        //setting priority marker color
        if(MTPriority == 2){ 
            MTContents.find(".mainMarker").css("background-color", "red");
        } else if(MTPriority == 1){
            MTContents.find(".mainMarker").css("background-color", "black");
        } else if(MTPriority == 0){
            MTContents.find(".mainMarker").css("background-color", "blue");
        }       

        MTContents.hide();
        $("#tasksWrapper").prepend(MTContents); 
        MTContents.slideDown(100);

        $("#tasksWrapper").sortable({
            axis: "y",
            scroll: "true",
            scrollSpeed : 10,
            scrollSensitivity: 10,
            handle: $(".holder")            
        });

    }
};
_

script.js:(。on()関数が下部にあるファイル)

_$(function(){
     $("#addMain, #mainCatInput").on('click keypress', function(evt){       
        if(evt.type == "click" || evt.type =="keypress"){
            if((evt.type =="click" && evt.target.id == "addMain") ||
                (evt.which == 13 && evt.target.id=="mainCatInput")){    
                    MainUtil.add();                                             
            }
        }
    });

    //Here's the event i'm talking about :
    $("div.mainTaskWrapper").on('click', '.checkButton' , function(){
        alert("test text");
    });
});
_
15
Rafael Adel

_div.mainTaskWrapper_が存在するようには見えません。

ドキュメント から(はい、実際には太字です):

イベントハンドラーは、現在選択されている要素にのみバインドされます。コードが.on()を呼び出すときに、それらがページに存在している必要があります。要素が存在し、選択できることを確認するには、ドキュメント内でイベントバインディングを実行します。ページのHTMLマークアップにある要素のハンドラー。

[...]

委任されたイベントハンドラーがアタッチされたときに存在することが保証されている要素を選択することにより、委任されたイベントを使用して、イベントハンドラーを頻繁にアタッチおよび削除する必要をなくすことができます。

代わりに、それを_#tasksWrapper_にバインドすることをお勧めします。

_$("#tasksWrapper").on('click', '.checkButton' , function(){
    alert("test text");
});
_
33
Felix Kling

私はこれが古い投稿であることを知っていますが、出くわした他の人にとって役立つかもしれません...

あなたは試すことができます:

jQuery('body')on.('DOMNodeInserted', '#yourdynamicallyaddeddiv', function () {
//Your button click event
});

ここに簡単な例があります- https://jsfiddle.net/8b0e2auu/

3
anti000gravity

古いonメソッドのように動作させるには、セレクターをdelegate(パラメーターとして)で指定する必要があります。そうしないと、イベントは現在div.mainTaskWrapperに一致する要素(まだ存在していません)にのみリンクされます。新しい要素を追加した後でイベントを再割り当てするか、#tasksWrapperやドキュメント自体などの既存の要素にイベントを追加する必要があります。

このページ の「イベントの直接およびデリゲート」を参照してください。

3
GolezTrol