動的に作成された要素のイベントバインディング?

Oct 15 2008

ページ上のすべての選択ボックスをループし、.hoverイベントをそれらにバインドして、幅をオンにして少し調整するコードが少しありますmouse on/off

これはページの準備ができたときに発生し、問題なく機能します。

私が抱えている問題は、最初のループの後にAjaxまたはDOMを介して追加した選択ボックスには、イベントがバインドされないことです。

このプラグイン(jQuery Live Query Plugin)を見つけましたが、プラグインを使用してページにさらに5kを追加する前に、jQueryを直接または別のオプションでこれを行う方法を誰かが知っているかどうかを確認したいと思います。

回答

2335 Popnoodles Jul 30 2009 at 22:34

jQuery 1.7以降jQuery.fn.on、セレクターパラメーターを入力して使用する必要があります。

$(staticAncestors).on(eventName, dynamicChild, function() {});

説明:

これはイベント委任と呼ばれ、次のように機能します。イベントは、staticAncestors処理する必要のある要素の静的な親()にアタッチされます。このjQueryハンドラーは、この要素または子孫要素の1つでイベントがトリガーされるたびにトリガーされます。次に、ハンドラーは、イベントをトリガーした要素がセレクター(dynamicChild)と一致するかどうかを確認します。一致する場合は、カスタムハンドラー関数が実行されます。


これ以前は、推奨されるアプローチは次を使用することでしたlive()。

$(selector).live( eventName, function(){} );

ただし、live()1.7で廃止on()され、1.9で完全に削除されました。live()署名:

$(selector).live( eventName, function(){} );

...次のon()署名に置き換えることができます。

$(document).on( eventName, selector, function(){} );

たとえば、ページがクラス名で要素を動的に作成してdosomethingいる場合、イベントをすでに存在する親にバインドします(これはここでの問題の要点です。バインドするために存在するものが必要です。バインドしないでください。動的コンテンツ)、これは可能です(そして最も簡単なオプション)はdocumentです。覚えてdocumentおいてくださいが、最も効率的なオプションではないかもしれません。

$(document).on('mouseover mouseout', '.dosomething', function(){
    // what you want to happen when mouseover and mouseout 
    // occurs on elements that match '.dosomething'
});

イベントがバインドされたときに存在する親は問題ありません。例えば

$('.buttons').on('click', 'button', function(){
    // do something here
});

に適用されます

<div class="buttons">
    <!-- <button>s that are generated dynamically and added here -->
</div>
388 RonenRabinovici Aug 09 2013 at 16:51

のドキュメントには適切な説明がありますjQuery.fn.on。

要するに:

イベントハンドラーは、現在選択されている要素にのみバインドされます。これらは、コードがを呼び出すときにページに存在している必要があります.on()

したがって、次の例で#dataTable tbody trは、コードが生成される前に存在している必要があります。

$("#dataTable tbody tr").on("click", function(event){ console.log($(this).text());
});

新しいHTMLがページに挿入されている場合は、次に説明するように、委任されたイベントを使用してイベントハンドラーをアタッチすることをお勧めします。

委任されたイベントには、後でドキュメントに追加される子孫要素からのイベントを処理できるという利点があります。たとえば、テーブルが存在するが、行がコードを使用して動的に追加された場合、以下がそれを処理します。

$("#dataTable tbody").on("click", "tr", function(event){ console.log($(this).text());
});

まだ作成されていない子孫要素のイベントを処理する機能に加えて、委任されたイベントのもう1つの利点は、多くの要素を監視する必要がある場合にオーバーヘッドがはるかに低くなる可能性があることです。に1,000行あるデータテーブルでtbody、最初のコード例はハンドラーを1,000要素にアタッチします。

委任イベントアプローチ(2番目のコード例)は、イベントハンドラーを1つの要素、にのみアタッチし、イベントはtbody1つのレベル(クリックさtrれたものからtbody)にバブルアップするだけで済みます。

注:委任されたイベントはSVGでは機能しません。

231 RamPatra Dec 09 2014 at 14:59

これは、ライブラリやプラグインを含まない純粋なJavaScriptソリューションです。

document.addEventListener('click', function (e) {
    if (hasClass(e.target, 'bu')) {
        // .bu clicked
        // Do your thing
    } else if (hasClass(e.target, 'test')) {
        // .test clicked
        // Do your other thing
    }
}, false);

どこにhasClassありますか

function hasClass(elem, className) {
    return elem.className.split(' ').indexOf(className) > -1;
}

Live demo

クレジットはDaveとSimeVidasに送られます

最新のJSを使用hasClassすると、次のように実装できます。

function hasClass(elem, className) {
    return elem.classList.contains(className);
}
76 nickf Oct 15 2008 at 06:31

オブジェクトを作成するときに、オブジェクトにイベントを追加できます。同じイベントを複数のオブジェクトに異なる時間に追加する場合は、名前付き関数を作成するのがよいでしょう。

var mouseOverHandler = function() {
    // Do stuff
};
var mouseOutHandler = function () {
    // Do stuff
};

$(function() { // On the document load, apply to existing elements $('select').hover(mouseOverHandler, mouseOutHandler);
});

// This next part would be in the callback from your Ajax call
$("<select></select>")
    .append( /* Your <option>s */ )
    .hover(mouseOverHandler, mouseOutHandler)
    .appendTo( /* Wherever you need the select box */ )
;
51 GregBorenstein Oct 15 2008 at 06:35

イベントバインディング呼び出しを関数にラップして、それを2回呼び出すことができます。1回はドキュメントの準備ができたとき、もう1回は新しいDOM要素を追加するイベントの後でです。これを行う場合は、既存の要素に同じイベントを2回バインドしないようにする必要があるため、既存のイベントのバインドを解除するか、(より適切に)新しく作成されたDOM要素にのみバインドする必要があります。コードは次のようになります。

function addCallbacks(eles){
    eles.hover(function(){alert("gotcha!")});
}

$(document).ready(function(){ addCallbacks($(".myEles"))
});

// ... add elements ...
addCallbacks($(".myNewElements"))
43 user670265 Mar 22 2011 at 05:35

;の.live()代わりに使用してみてください.bind().live()結合する.hoverAjaxリクエストを実行した後、あなたのチェックボックスに。

32 MadeInDreams Jan 22 2016 at 08:06

動的に作成された要素のイベントバインディング

単一要素:

$(document.body).on('click','.element', function(e) {  });

子要素:

 $(document.body).on('click','.element *', function(e) {  });

追加され*たに注意してください。その要素のすべての子に対してイベントがトリガーされます。

私はそれに気づきました:

$(document.body).on('click','.#element_id > element', function(e) {  });

それはもう機能していませんが、以前は機能していました。Google CDNのjQueryを使用していますが、変更されたかどうかはわかりません。

27 Fazi Dec 21 2011 at 14:26

live()メソッドを使用して、要素(新しく作成された要素も含む)をonclickイベントなどのイベントやハンドラーにバインドできます。

これが私が書いたサンプルコードです。ここでは、live()メソッドが選択された要素(新しく作成された要素も含む)をイベントにバインドする方法を確認できます。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>Untitled Document</title>
    </head>

    <body>
        <script src="http://code.jquery.com/jquery-latest.js"></script>
        <script src="http://ajax.aspnetcdn.com/ajax/jquery.ui/1.8.16/jquery-ui.min.js"></script>

        <input type="button" id="theButton" value="Click" />
        <script type="text/javascript">
            $(document).ready(function() { $('.FOO').live("click", function (){alert("It Works!")});
                    var $dialog = $('<div></div>').html('<div id="container"><input type ="button" id="CUSTOM" value="click"/>This dialog will show every time!</div>').dialog({
                                                                                                         autoOpen: false,
                                                                                                         tite: 'Basic Dialog'
                                                                                                     });
                    $('#theButton').click(function() { $dialog.dialog('open');
                        return('false');
                    });
                    $('#CUSTOM').click(function(){ //$('#container').append('<input type="button" value="clickmee" class="FOO" /></br>');
                        var button = document.createElement("input");
                        button.setAttribute('class','FOO');
                        button.setAttribute('type','button');
                        button.setAttribute('value','CLICKMEE');
                        $('#container').append(button); }); /* $('#FOO').click(function(){
                                                     alert("It Works!");
                                                 }); */
            });
        </script>
    </body>
</html>
27 Vatsal Nov 21 2015 at 19:01

私はセレクターを使用することを好み、それをドキュメントに適用します。

これはドキュメントにバインドされ、ページの読み込み後にレンダリングされる要素に適用されます。

例えば:

$(document).on("click", 'selector', function() {
    // Your code here
});
22 MartinDaRosa Oct 08 2015 at 00:43

別の解決策は、要素を作成するときにリスナーを追加することです。リスナーを本体に配置する代わりに、作成した瞬間にリスナーを要素に配置します。

var myElement = $('<button/>', {
    text: 'Go to Google!'
});

myElement.bind( 'click', goToGoogle);
myElement.append('body');


function goToGoogle(event){
    window.location.replace("http://www.google.com");
}
20 RohitSuthar Jun 30 2016 at 13:25

このようにしてみてください-

$(document).on( 'click', '.click-activity', function () { ... });
20 MustkeemK Jun 14 2018 at 18:15

これは、イベントの委任によって行われます。イベントはラッパークラス要素にバインドされますが、セレクタークラス要素に委任されます。これがその仕組みです。

$('.wrapper-class').on("click", '.selector-class', function() {
    // Your code here
});

そしてHTML

<div class="wrapper-class">
    <button class="selector-class">
      Click Me!
    </button>
</div>    

#注:ラッパークラス要素は、たとえば何でもかまいません。ドキュメント、本文、またはラッパー。ラッパーはすでに存在しているはずです。ただし、selector必ずしもページの読み込み時に表示する必要はありません。後で来る可能性があり、イベントはselector 必ずバインドされます。

17 AslanKaya Mar 26 2016 at 09:15

要素が配置されている「MAIN」クラスに注意してください。たとえば、

<div class="container">
     <ul class="select">
         <li> First</li>
         <li>Second</li>
    </ul>
</div>

上記のシナリオでは、jQueryが監視するMAINオブジェクトは「コンテナ」です。

そして、あなたは基本的にのようなコンテナの下に要素名を持つことになりますulliselect

$(document).ready(function(e) { $('.container').on( 'click',".select", function(e) {
        alert("CLICKED");
    });
 });
15 MensurGrišević Aug 11 2016 at 23:16

you could use

$('.buttons').on('click', 'button', function(){
    // your magic goes here
});

or

$('.buttons').delegate('button', 'click', function() {
    // your magic goes here
});

these two methods are equivalent but have a different order of parameters.

see: jQuery Delegate Event

15 guest271314 Apr 05 2017 at 14:11

You can attach event to element when dynamically created using jQuery(html, attributes).

As of jQuery 1.8, any jQuery instance method (a method of jQuery.fn) can be used as a property of the object passed to the second parameter:

function handleDynamicElementEvent(event) {
  console.log(event.type, this.value)
}
// create and attach event to dynamic element
jQuery("<select>", {
    html: $.map(Array(3), function(_, index) {
      return new Option(index, index)
    }),
    on: {
      change: handleDynamicElementEvent
    }
  })
  .appendTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>

12 leaf Sep 16 2017 at 14:01

Here is why dynamically created elements do not respond to clicks :

var body = $("body"); var btns = $("button");
var btnB = $("<button>B</button>"); // `<button>B</button>` is not yet in the document. // Thus, `$("button")` gives `[<button>A</button>]`.
// Only `<button>A</button>` gets a click listener.
btns.on("click", function () {
  console.log(this);
});
// Too late for `<button>B</button>`...
body.append(btnB);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

As a workaround, you have to listen to all clicks and check the source element :

var body = $("body"); var btnB = $("<button>B</button>");
var btnC = $("<button>C</button>"); // Listen to all clicks and // check if the source element // is a `<button></button>`. body.on("click", function (ev) { if ($(ev.target).is("button")) {
    console.log(ev.target);
  }
});
// Now you can add any number
// of `<button></button>`.
body.append(btnB);
body.append(btnC);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

This is called "Event Delegation". Good news, it's a builtin feature in jQuery :-)

var i = 11;
var body = $("body"); body.on("click", "button", function () { var letter = (i++).toString(36).toUpperCase(); body.append($("<button>" + letter + "</button>"));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button>A</button>

11 AnkitKathiriya Dec 18 2015 at 15:48

Any parent that exists at the time the event is bound and if your page was dynamically creating elements with the class name button you would bind the event to a parent which already exists

$(document).ready(function(){ //Particular Parent chield click $(".buttons").on("click","button",function(){
    alert("Clicked");
  });  
  
  //Dynamic event bind on button class  
  $(document).on("click",".button",function(){ alert("Dymamic Clicked"); }); $("input").addClass("button");  
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="buttons">
  <input type="button" value="1">
  <button>2</button>
  <input type="text">
  <button>3</button>  
  <input type="button" value="5">  
  </div>
<button>6</button>

10 truongnm Jun 08 2018 at 09:29

Bind the event to a parent which already exists:

$(document).on("click", "selector", function() {
    // Your code here
});
5 KalpeshPatel Nov 30 2016 at 16:07

Use the .on() method of jQuery http://api.jquery.com/on/ to attach event handlers to live element.

Also as of version 1.9 .live() method is removed.

5 PrasadDeSilva Apr 19 2017 at 02:47

Another flexible solution to create elements and bind events (source)

// creating a dynamic element (container div)
var $div = $("<div>", {id: 'myid1', class: 'myclass'});

//creating a dynamic button
 var $btn = $("<button>", { type: 'button', text: 'Click me', class: 'btn' });

// binding the event
 $btn.click(function () { //for mouseover--> $btn.on('mouseover', function () {
    console.log('clicked');
 });

// append dynamic button to the dynamic container
$div.append($btn);

// add the dynamically created element(s) to a static element
$("#box").append($div);

Note: This will create an event handler instance for each element (may affect performance when used in loops)

4 RonnieRoyston Jun 08 2018 at 09:53

I prefer to have event listeners deployed in a modular function fashion rather than scripting a document level event listener. So, I do like below. Note, you can't oversubscribe an element with the same event listener so don't worry about attaching a listener more than once - only one sticks.

var iterations = 4;
var button;
var body = document.querySelector("body");

for (var i = 0; i < iterations; i++) {
    button = document.createElement("button");
    button.classList.add("my-button");
    button.appendChild(document.createTextNode(i));
    button.addEventListener("click", myButtonWasClicked);
    body.appendChild(button);
}

function myButtonWasClicked(e) {
    console.log(e.target); //access to this specific button
}

FakhrulHasan Sep 27 2017 at 22:42
<html>
    <head>
        <title>HTML Document</title>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.0/jquery.min.js"></script>
    </head>

    <body>
        <div id="hover-id">
            Hello World
        </div>

        <script>
            jQuery(document).ready(function($){ $(document).on('mouseover', '#hover-id', function(){
                    $(this).css('color','yellowgreen'); }); $(document).on('mouseout', '#hover-id', function(){
                    $(this).css('color','black');
                });
            });
        </script>
    </body>
</html>
Evhz May 18 2018 at 07:13

I was looking a solution to get $.bind and $.unbind working without problems in dynamically added elements.

As on() makes the trick to attach events, in order to create a fake unbind on those I came to:

const sendAction = function(e){ ... }
// bind the click
$('body').on('click', 'button.send', sendAction ); // unbind the click $('body').on('click', 'button.send', function(){} );