Associazione di eventi su elementi creati dynamicmente?

Ho un po ‘di codice dove sto facendo il giro di tutte le caselle di selezione in una pagina e .hover un evento .hover a loro per fare un po’ di giocherellando con la loro larghezza sul mouse on/off .

Questo succede a pagina pronta e funziona bene.

Il problema che ho è che ogni casella di selezione che aggiungo tramite Ajax o DOM dopo il ciclo iniziale non avrà l’evento associato.

Ho trovato questo plugin ( jQuery Live Query Plugin ), ma prima di aggiungere un altro 5k alle mie pagine con un plugin, voglio vedere se qualcuno sa come farlo, sia con jQuery direttamente che con un’altra opzione.

A partire da jQuery 1.7 dovresti usare jQuery.fn.on :

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

Prima di questo , l’approccio consigliato era usare live() :

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

Tuttavia, live() stato deprecato in 1.7 a favore di on() e completamente rimosso in 1.9. La firma live() :

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

… può essere sostituito con la seguente firma on() :

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

Ad esempio, se la tua pagina creava dynamicmente elementi con il nome della class dosomething dovresti associare l’evento a un genitore che esiste già (questo è il nocciolo del problema qui, hai bisogno di qualcosa che esiste per associare, non associare a il contenuto dinamico), questo può essere (e l’opzione più semplice) è il document . Sebbene tenere a mente il document potrebbe non essere l’opzione più efficiente .

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

Qualsiasi genitore esistente al momento in cui l’evento è associato va bene. Per esempio

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

si applicherebbe a

 

C’è una buona spiegazione nella documentazione di jQuery.fn.on .

In breve:

I gestori di eventi sono associati solo agli elementi attualmente selezionati; devono esistere nella pagina nel momento in cui il tuo codice effettua la chiamata a .on() .

Quindi nel seguente esempio #dataTable tbody tr deve esistere prima che il codice venga generato.

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

Se il nuovo codice HTML viene iniettato nella pagina, è preferibile utilizzare gli eventi delegati per colbind un gestore di eventi, come descritto di seguito.

Gli eventi delegati hanno il vantaggio di poter elaborare eventi da elementi discendenti che vengono aggiunti al documento in un secondo momento. Ad esempio, se la tabella esiste, ma le righe vengono aggiunte dynamicmente utilizzando il codice, il seguente lo gestirà:

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

Oltre alla loro capacità di gestire eventi su elementi discendenti che non sono ancora stati creati, un altro vantaggio degli eventi delegati è il loro potenziale per un sovraccarico molto più basso quando molti elementi devono essere monitorati. Su una tabella di dati con 1.000 righe nel suo tbody , il primo esempio di codice allega un gestore a 1.000 elementi.

Un approccio ad eventi delegati (il secondo esempio di codice) allega un gestore di eventi a un solo elemento, il tbody , e l’evento deve solo risalire di un livello (dalla tr clic a tbody ).

Nota: gli eventi delegati non funzionano per SVG .

Questa è una pura soluzione JavaScript senza librerie o plugin:

 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); 

dove hasClass è

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

Dimostrazione dal vivo

Il merito va a Dave e Sime Vidas

Usando un JS più moderno, hasClass può essere implementato come:

 function hasClass(elem, className) { return elem.classList.contains(className); } 

Puoi aggiungere eventi agli oggetti quando li crei. Se stai aggiungendo gli stessi eventi a più oggetti in momentjs diversi, la creazione di una funzione con nome potrebbe essere la soluzione giusta.

 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 $("") .append( /* Your  

Potresti semplicemente racchiudere il richiamo dell’evento in una funzione e quindi invocarlo due volte: una volta sul documento pronto e una volta dopo l’evento che aggiunge i nuovi elementi DOM. Se lo fai, eviterai di bind lo stesso evento due volte sugli elementi esistenti, quindi è necessario separare gli eventi esistenti o (meglio) legarli solo agli elementi DOM che sono stati appena creati. Il codice sarebbe simile a questo:

 function addCallbacks(eles){ eles.hover(function(){alert("gotcha!")}); } $(document).ready(function(){ addCallbacks($(".myEles")) }); // ... add elements ... addCallbacks($(".myNewElements")) 

Prova a usare .live() invece di .bind() ; il .live() eseguirà il binding. .hover alla casella di controllo dopo l’esecuzione della richiesta Ajax.

È ansible utilizzare il metodo live () per associare elementi (anche quelli appena creati) ad eventi e gestori, come l’evento onclick.

Ecco un esempio di codice che ho scritto, in cui puoi vedere come il metodo live () lega gli elementi scelti, anche quelli appena creati, agli eventi:

     Untitled Document         

Associazione di eventi su elementi creati dynamicmente

Singolo elemento:

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

Elemento figlio:

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

Si noti l’aggiunta * . Un evento verrà triggersto per tutti i bambini di quell’elemento.

Ho notato che:

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

Non funziona più, ma funzionava prima. Ho usato jQuery da Google CDN , ma non so se l’hanno cambiato.

Un’altra soluzione è aggiungere il listener durante la creazione dell’elemento. Invece di mettere l’ascoltatore nel corpo, metti l’ascoltatore nell’elemento nel momento in cui lo crei:

 var myElement = $('', { text: 'Go to Google!' }); myElement.bind( 'click', goToGoogle); myElement.append('body'); function goToGoogle(event){ window.location.replace("http://www.google.com"); } 

Preferisco usare il selettore e lo applico sul documento.

Questo si lega al documento e sarà applicabile agli elementi che verranno renderizzati dopo il caricamento della pagina.

Per esempio:

 $(document).on("click", $(selector), function() { // Your code here }); 

Prendi nota della class “MAIN” in cui è posizionato l’elemento, ad esempio

 
  • First
  • Second

Nello scenario di cui sopra, l’object principale che jQuery guarderà è “contenitore”.

Quindi avrai fondamentalmente nomi di elementi sotto contenitore come ul , li , e select :

 $(document).ready(function(e) { $('.container').on( 'click',".select", function(e) { alert("CLICKED"); }); }); 

È ansible associare un evento all’elemento quando viene creato dynamicmente utilizzando jQuery(html, attributes) .

A partire da jQuery 1.8 , qualsiasi metodo di istanza jQuery (un metodo di jQuery.fn ) può essere utilizzato come una proprietà dell’object passato al secondo parametro:

 function handleDynamicElementEvent(event) { console.log(event.type, this.value) } // create and attach event to dynamic element jQuery(" 
  

potresti usare

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

o

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

questi due metodi sono equivalenti ma hanno un diverso ordine di parametri.

vedere: Evento Delegato jQuery

Qualsiasi p arente esistente al momento in cui l’evento è associato e se la tua pagina creava dynamicmente elementi con il pulsante del nome della class dovresti associare l’evento a un genitore che esiste già

 $(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"); }); 
  

Ecco perché gli elementi creati dynamicmente non rispondono ai clic:

 var body = $("body"); var btns = $("button"); var btnB = $(""); // `` is not yet in the document. // Thus, `$("button")` gives `[]`. // Only `` gets a click listener. btns.on("click", function () { console.log(this); }); // Too late for ``... body.append(btnB); 
   

Prova così –

 $(document).on( 'click', '.click-activity', function () { ... }); 

Usa il metodo .on() di jQuery http://api.jquery.com/on/ per colbind i gestori di eventi all’elemento live.

Anche a partire dalla versione 1.9 il metodo .live() viene rimosso.

Soluzione più flessibile per creare elementi e associare eventi ( fonte )

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

Nota: questo creerà un’istanza del gestore di eventi per ogni elemento (potrebbe influire sulle prestazioni se utilizzato nei loop)

Associare l’evento a un genitore già esistente:

 $(document).on("click", "selector", function() { // Your code here }); 

Stavo cercando una soluzione per ottenere $.bind e $.unbind funzionanti senza problemi negli elementi aggiunti dynamicmente.

Come su () rende il trucco per albind eventi, al fine di creare un falso unbind su quelli che sono venuto a:

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

Preferisco che i listener di eventi siano distribuiti in una funzione modulare anziché utilizzare un listener di eventi a livello di document . Quindi, mi piace di seguito. Nota, non puoi sottoscrivere un elemento in eccesso con lo stesso listener di eventi, quindi non preoccuparti di colbind un listener più di una volta: solo uno stick.

 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 } 

Questo viene fatto dalla delega degli eventi. L’evento si collegherà all’elemento wrapper-class ma sarà delegato all’elemento selector-class. Ecco come funziona.

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

Nota:

l’elemento wrapper-class può essere qualsiasi cosa ex. documento, corpo o il tuo wrapper. Il wrapper dovrebbe già esistere.

   HTML Document    
Hello World