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

1677
Eli 2008-10-15 13:25.

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

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

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

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

23 answers

2335
Popnoodles 2009-07-31 05: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
Ronen Rabinovici 2013-08-09 23: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
Ram Patra 2014-12-09 21: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 2008-10-15 13: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
Greg Borenstein 2008-10-15 13: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 2011-03-22 12:35.

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

32
MadeInDreams 2016-01-22 15: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 2011-12-21 21: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 2015-11-22 02:01.

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

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

例えば:

$(document).on("click", 'selector', function() {
    // Your code here
});
22
Martin Da Rosa 2015-10-08 07: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
Rohit Suthar 2016-06-30 20:25.

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

$(document).on( 'click', '.click-activity', function () { ... });
20
Mustkeem K 2018-06-15 01: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
Aslan Kaya 2016-03-26 16: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
Mensur Grišević 2016-08-12 06: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 2017-04-05 21: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 2017-09-16 21: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
Ankit Kathiriya 2015-12-18 22: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 2018-06-08 16:29.

Bind the event to a parent which already exists:

$(document).on("click", "selector", function() {
    // Your code here
});
5
Kalpesh Patel 2016-11-30 23: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
Prasad De Silva 2017-04-19 09: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
Ronnie Royston 2018-06-08 16: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
}

0
Fakhrul Hasan 2017-09-28 05: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>
0
Evhz 2018-05-18 14: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(){} );

Related questions

MORE COOL STUFF

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは3日間一緒に夫と一緒に寝て、25年経ってもまだ夫と結婚しています

ケイト・ブランシェットは、夫に会ったとき、典型的な交際のアドバイスに逆らいました。

マイケルシーンが非営利の俳優である理由

マイケルシーンが非営利の俳優である理由

マイケルシーンは非営利の俳優ですが、それは正確にはどういう意味ですか?

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

ホールマークスターのコリンエッグレスフィールドがRomaDramaLiveでスリル満点のファンと出会う![エクスクルーシブ]

特徴的なスターのコリン・エッグレスフィールドは、RomaDrama Liveでのスリル満点のファンとの出会いについて料理しました!加えて、大会での彼のINSPIREプログラム。

「たどりつけば」をオンラインでストリーミングできない理由

「たどりつけば」をオンラインでストリーミングできない理由

ノーザンエクスポージャーが90年代の最も人気のある番組の1つになった理由を確認するには、Blu-rayまたはDVDプレーヤーをほこりで払う必要があります。

バイオニック読書はあなたをより速く読むことができますか?

バイオニック読書はあなたをより速く読むことができますか?

BionicReadingアプリの人気が爆発的に高まっています。しかし、それは本当にあなたを速読術にすることができますか?

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖:アクセスは簡単ではありませんが、ハイキングする価値があります

ドミニカのボイリング湖は、世界で2番目に大きいボイリング湖です。そこにたどり着くまでのトレッキングは大変で長いですが、努力する価値は十分にあります。

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

私たちの水をきれいに保つのを助けるためにあなたの髪を寄付してください

サロンからのヘアトリミングや個人的な寄付は、油流出を吸収して環境を保護するのに役立つマットとして再利用できます。

ホワイトハウスの最も記憶に残る結婚式を見てください

ホワイトハウスの最も記憶に残る結婚式を見てください

過去200年以上の間にホワイトハウスで結婚したのはほんの数人です。彼らは誰でしたか、そしてそこで結婚式を獲得するために何が必要ですか?

アトランタのドナ・ブラジル:「私があなたに私の話をするとき私を踏まないでください」

アトランタのドナ・ブラジル:「私があなたに私の話をするとき私を踏まないでください」

2017年11月19日にアトランタで開催されたドナブラジルとモーアイボリー(ダグスミスフォトグラフィー)ドナブラジルを見逃すことはありません。

彼らは北朝鮮から脱出した亡命者の胃の中に奇妙な寄生虫を見つけました

彼らは北朝鮮から脱出した亡命者の胃の中に奇妙な寄生虫を見つけました

画像:ゲッティ陰謀愛好家は新しくてエキサイティングなディスカッション資料を持っています:国境を越えて韓国に5発撃たれた北朝鮮の脱北者は寄生虫でいっぱいで、そのうちの1人は南のメディアは、寄生虫を持った北朝鮮の脱北者を見つけることは珍しいことではないと報告している、実際、男性が30以上のタイプを持っていたケースがあった。

パニッシャーの第2話は、複雑な陰謀の網を織り交ぜています

パニッシャーの第2話は、複雑な陰謀の網を織り交ぜています

写真:パニッシャー(Netflix)これらのMarvel Netflixが愛していることが1つあるとすれば、それは複雑な政府や企業の陰謀です。そして、なぜこれらのショーがそのルートを選択するのかを理解するのは簡単です。

最新のBoseヘッドフォンは音楽を聴くためのものではなく、パートナーの鼻を鳴らすためのものです。

最新のBoseヘッドフォンは音楽を聴くためのものではなく、パートナーの鼻を鳴らすためのものです。

あなたのパートナーはチェーンソーのように詮索し、あなたを眠らせませんか?あなたのパートナーはあなたがチェーンソーのように詮索したと主張しますが、あなたが詮索しないので彼らは彼の想像ですか?あなたのケースが何であれ、Bose(はい、ハイエンドオーディオ機器のメーカー)はあなたのために何かを持っています。それらはBoseSleepbudsと呼ばれます。

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya Wishes Boyfriend Tom Holland Happy Birthday with Cuddly Photo: He 'Makes Me the Happiest'

Zendaya shared a sweet photo in honor of boyfriend Tom Holland's 26th birthday Wednesday

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

小さな女性:脳卒中を患った後に病院から解放されたアトランタのジューシーな赤ちゃん:「まだ癒し」

シーレン「Ms.JuicyBaby」ピアソンは、先月脳卒中で入院した後、「もう一度たくさんのことをする方法を学ばなければならない」ため、言語療法を受けていることを明らかにしました。

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

エマストーンは彼女のクリフサイドマリブビーチハウスを420万ドルでリストアップしています—中を見てください!

オスカー受賞者の世紀半ばの家には、3つのベッドルーム、2つのバス、オーシャンフロントの景色があります。

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、母乳育児の経験の中で、彼女は「本当に、本当に落ち込んでいる」と言います

ジーニー・メイ・ジェンキンスは、生後4か月の娘、モナコに母乳育児をしていると語った。

投資ノート:Bioscout AU$300万シード

投資ノート:Bioscout AU$300万シード

Bioscoutは、農家を運転席に置くという使命を負っています。Artesian(GrainInnovate)やUniseedと並んで、最新のシードラウンドでチームを支援できることをうれしく思います。問題真菌症による重大な作物の損失は、農民にとって試練であることが証明されています。

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

リトルマーケットリサーチ1| 2022年のクイックグリンプス遠隔医療市場

遠隔医療は、パンデミック後の時代では新しいものではなく、時代遅れの分野でもありません。しかし、業界を詳しく見ると、需要と供給の強力な持続可能性と、米国で絶え間ない革命となる強力な潜在的成長曲線を示しています。

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

スタートアップ資金調達環境:タイのスタートアップエコシステムの次は何ですか?

2021年は、世界的なベンチャーキャピタル(VC)の資金調達にとって記録的な年でした。DealStreetAsiaによると、東南アジアも例外ではなく、この地域では年間で記録的な25の新しいユニコーンが採掘されました。

ムーアの法則を超えて

ムーアの法則を超えて

計算に対する私たちの欲求とムーアの法則が提供できるものとの間には、指数関数的に増大するギャップがあります。私たちの文明は計算に基づいています—建築と想像力の現在の限界を超える技術を見つけなければなりません。

Language