Событие клика не работает с динамически генерируемыми элементами

<html>
<head>
    <script type="text/javascript" src="jquery.js"></script>
    <script type="text/javascript">

        $(document).ready(function() {

            $("button").click(function() {
                $("h2").html("<p class='test'>click me</p>")
            });   

            $(".test").click(function(){
                alert();
            });
        });

    </script>
</head>
<body>
    <h2></h2>
    <button>generate new element</button>
</body>
</html>

Я пытался сгенерировать новый тег с именем класса test в <h2> нажав на кнопку. Я также определил событие клика, связанное с test, Но событие не работает.

Кто-нибудь может помочь?

20 ответов

Решение

click() используемая привязка называется "прямой" привязкой, которая прикрепляет обработчик только к уже существующим элементам. Он не будет привязан к элементам, созданным в будущем. Для этого вам нужно создать "делегированную" привязку с помощью on(),

Преимущество делегированных событий заключается в том, что они могут обрабатывать события от элементов-потомков, которые добавляются в документ позднее.

Источник

Вот что вы ищете:

var counter = 0;

$("button").click(function() {
    $("h2").append("<p class='test'>click me " + (++counter) + "</p>")
});

// With on():

$("h2").on("click", "p.test", function(){
    alert($(this).text());
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<h2></h2>
<button>generate new element</button>

Вышесказанное работает для тех, кто использует jQuery версии 1.7+. Если вы используете более старую версию, обратитесь к предыдущему ответу ниже.


Предыдущий ответ:

Попробуйте использовать live():

$("button").click(function(){
    $("h2").html("<p class='test'>click me</p>")
});   


$(".test").live('click', function(){
    alert('you clicked me!');
});

Работал на меня. Пробовал с jsFiddle.

Или есть новый способ сделать это с delegate():

$("h2").delegate("p", "click", function(){
    alert('you clicked me again!');
});

Обновленный jsFiddle.

Использовать .on() метод с делегированными событиями

$('#staticParent').on('click', '.dynamicElement', function() {
    // Do something on an existent or future .dynamicElement
});

.on()Метод позволяет вам делегировать любой желаемый обработчик события:
текущие элементы или будущие элементы добавляются в DOM позднее.

PS: не используйте .live() ! Из jQuery 1.7+ .live() метод устарел.

Причина:

В jQuery Click()- присоединяет обработчик событий, только если элемент уже существует в HTML-коде.

Он не будет учитывать новый элемент, который создается динамически (элемент Future) после загрузки страницы.

Динамические элементы создаются с помощью javascript или jquery(не в html).

Таким образом, событие щелчка не срабатывает.

Решение:

Чтобы преодолеть это, мы должны использовать функцию ().

Функцииделегата (), live () и on () имеют преимущества перед элементами DOM.

on может активировать как существующие элементы, так и будущие элементы.

Он может рассмотреть элементы, которые присутствуют на всей странице.

Функции делегата (), live () устарели (не используйте их).

Вы должны использовать функцию on для запуска события на динамически создаваемых (будущих) элементах.

Удалить код из $(document).ready:

$(".test").click(function(){

  alert();

});

Изменить на:

$(document).on('click','.test',function(){

  alert('Clicked');

});

Добавьте эту функцию в ваш файл js. Это будет работать на каждом браузере

$(function() {
    $(document).on("click", '#mydiv', function() {
        alert("You have just clicked on ");
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='mydiv'>Div</div>

Вам нужно использовать .live, чтобы это работало:

$(".test").live("click", function(){
   alert();
});

или если вы используете jquery 1.7+, используйте .on:

$(".test").on("click", "p", function(){
   alert();
});

+ Изменить

 $(".test").click(function(){

к

 $(".test").live('click', function(){

LIVE DEMO

JQuery.live()

Пытаться .live() или же .delegate()

http://api.jquery.com/live/

http://api.jquery.com/delegate/

Ваш .test элемент был добавлен после .click() метод, поэтому к нему не было прикреплено событие. Live и Delegate передают этот триггер события родительским элементам, которые проверяют своих потомков, поэтому все, что было добавлено впоследствии, все еще работает Я думаю, что Live проверит все тело документа, в то время как Делегат может быть передан элементу, поэтому Делегат более эффективен.

Больше информации:

http://www.alfajango.com/blog/the-difference-between-jquerys-bind-live-and-delegate/

Я нашел два решения в документации jQuery:

Во-первых: используйте делегата в теле или документе

Например:

 $("body").delegate('.test', 'click', function(){
 ...
  alert('test');
 });

Зачем?

Ответ: Присоедините обработчик к одному или нескольким событиям для всех элементов, которые соответствуют селектору, сейчас или в будущем, на основе определенного набора корневых элементов. ссылка: http://api.jquery.com/delegate/

Второе: поместите вашу функцию в "$ (document)", используя "on", и присоедините ее к элементу, который вы хотите вызвать. Первый параметр - это "обработчик события", второй - элемент, а третий - функция. Например:

 $( document ).on( 'click', '.test', function () {
 ...
  alert('test');
 });

Зачем?

Ответ: обработчики событий привязаны только к выбранным в данный момент элементам; они должны существовать на странице в тот момент, когда ваш код вызывает .on (). Чтобы убедиться, что элементы присутствуют и могут быть выбраны, выполните привязку событий внутри обработчика готовых документов для элементов, которые находятся в разметке HTML на странице. Если на страницу внедряется новый HTML, выберите элементы и прикрепите обработчики событий после того, как новый HTML будет помещен на страницу. Или используйте делегированные события для присоединения обработчика событий, как описано далее... ссылка: https://api.jquery.com/on/

Лучший способ применить событие к динамически генерируемому контенту с помощью делегирования.

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

так что ваш код сейчас такой

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

Альтернативная и более краткая альтернатива (IMHO) заключается в использовании необработанной функции javascript, которая реагирует на событие нажатия, а затем, если хотите, передает целевой элемент обратно в jQuery. Преимущество этого подхода заключается в том, что вы можете динамически добавлять свой элемент в любом месте, и обработчик кликов будет "просто работать", и вам не нужно заботиться о делегировании управления родительским элементам и т. Д.

Шаг 1. Обновите динамический HTML-файл, чтобы запустить событие onclick. Обязательно передайте объект 'event' в качестве аргумента

    $ ("кнопка"). click (function () {
        $ ("h2"). html ("

onclick = 'test (event)' > click me ") });

Шаг 2. Создайте тестовую функцию для ответа на событие нажатия

    функциональный тест (e){
        предупреждение ();
    });

Необязательный шаг 3: учитывая, что вы используете jQuery, я предполагаю, что будет полезно получить ссылку на кнопку источника

    функциональный тест (e){
        предупреждение ();

        // Получить ссылку на кнопку
        // Объяснение этой строки доступно здесь
        var target = (e.target)? e.target: e.srcElement;

        // Передаем ссылку на кнопку в jQuery, чтобы сделать магию jQuery
        var $ btn = $ (target);

    });

Проблема в том, что вы пытаетесь связать класс "test" с событием до того, как в DOM, Хотя может показаться, что все это динамично, на самом деле происходит JQuery делает проход через DOM и подключает событие щелчка, когда ready() Функция срабатывает, что происходит до того, как вы создали "Click Me" в вашей кнопке события.

Добавляя событие "test" Click в обработчик нажатия "button", оно подключается к нему после того, как в DOM,

<script type="text/javascript">
    $(document).ready(function(){                          
        $("button").click(function(){                                  
            $("h2").html("<p class='test'>click me</p>")                          
            $(".test").click(function(){                          
                alert()                          
            });       
        });                                     
    });
</script>

С помощью live() (как уже указывали другие) - это еще один способ сделать это, но я чувствовал, что было бы неплохо указать на небольшую ошибку в вашем коде JS. То, что вы написали, было не так, просто нужно было правильно определить область. Понимая, как DOM и JS works - одна из хитрых вещей для многих традиционных разработчиков.

live() это более чистый способ справиться с этим и в большинстве случаев это правильный путь. Это по сути наблюдает за DOM и перемонтировать вещи всякий раз, когда элементы внутри него меняются.

$(.surrounding_div_class).on( 'click', '.test', function () {
alert( 'WORKS!' );
});

Работает только в том случае, если DIV с классом.surrounding_div_class является непосредственным родителем объекта.test

Если в div есть другой объект, который будет заполнен, он не будет работать.

Если у вас есть динамически добавленная ссылка на какой-либо контейнер или тело:

var newLink= $("<a></a>", {
        "id": "approve-ctrl",
        "href": "#approve",
        "class": "status-ctrl",
        "data-attributes": "DATA"
    }).html("Its ok").appendTo(document.body);

вы можете взять его необработанный элемент javascript и добавить к нему прослушиватель событий, например, click:

newLink.get(0).addEventListener("click", doActionFunction);

Независимо от того, сколько раз вы добавляете этот новый экземпляр ссылки, вы можете использовать его, как если бы вы использовали jquery click функция.

function doActionFunction(e) {
    e.preventDefault();
    e.stopPropagation();

    alert($(this).html());
}

Таким образом, вы получите сообщение о том,

Все нормально

Он имеет лучшую производительность, чем другие альтернативы.

Дополнительно: вы можете получить лучшую производительность, избегая jquery и используя обычный javascript. Если вы используете IE до версии 8, вы должны использовать этот polyfill для использования метода addEventListener

if (typeof Element.prototype.addEventListener === 'undefined') {
    Element.prototype.addEventListener = function (e, callback) {
      e = 'on' + e;
      return this.attachEvent(e, callback);
    };
  }

.live функция работает отлично.

Это для динамически добавленных элементов на сцене.

$('#selectAllAssetTypes').live('click', function(event){
                    alert("BUTTON CLICKED");
                    $('.assetTypeCheckBox').attr('checked', true);
                });

Ура, Анкит.

Я работаю с таблицами, добавляя к ним новые элементы динамически, и при использовании on () единственный способ заставить меня работать, это использовать нединамический родительский элемент как:

<table id="myTable">
    <tr>
        <td></td> // Dynamically created
        <td></td> // Dynamically created
        <td></td> // Dynamically created
    </tr>
</table>

<input id="myButton" type="button" value="Push me!">

<script>
    $('#myButton').click(function() {
        $('#myTable tr').append('<td></td>');
    });

    $('#myTable').on('click', 'td', function() {
        // Your amazing code here!
    });
</script>

Это действительно полезно, потому что для удаления событий, связанных с on (), вы можете использовать off (), а чтобы использовать события один раз, вы можете использовать one ().

Jquery .on работает нормально, но у меня были некоторые проблемы с рендерингом, реализующим некоторые решения выше. Моя проблема с использованием .on является то, что каким-то образом это делает события иначе, чем .hover метод.

Просто для кого-то еще, у кого также может быть проблема. Я решил свою проблему, перерегистрировав событие наведения для динамически добавляемого элемента:

Перерегистрируйте событие hover, потому что hover не работает для динамически создаваемых элементов. поэтому каждый раз, когда я создаю новый / динамический элемент, я снова добавляю код наведения мыши. работает отлично

$('#someID div:last').hover(
    function() {
       //...
    },
    function() {
       //...
    }
);

Я не мог получить живой или делегировать работать над div в лайтбоксе (tinybox).

Я успешно использовал setTimeout следующим простым способом:

$('#displayContact').click(function() {
    TINY.box.show({html:'<form><textarea id="contactText"></textarea><div id="contactSubmit">Submit</div></form>', close:true});
    setTimeout(setContactClick, 1000);
})

function setContactClick() {
    $('#contactSubmit').click(function() {
        alert($('#contactText').val());
    })
}

Также вы можете использовать onclick="do_something(this)"внутренний элемент

Вы можете добавлять по клику к динамически создаваемым элементам. Пример ниже. Использование Когда, чтобы убедиться, что это сделано. В моем примере я беру div с расширением класса, добавляю промежуток "нажмите, чтобы увидеть больше", а затем использую этот промежуток, чтобы скрыть / показать исходный div.

$.when($(".expand").before("<span class='clickActivate'>Click to see more</span>")).then(function(){
    $(".clickActivate").click(function(){
        $(this).next().toggle();
    })
});

Используйте "on", когда щелчок связывается с уже присутствующими элементами.

Например,

$('test').on('click',function(){
    alert('Test');
})

Это поможет.

Другие вопросы по тегам