JQuery как связать событие onclick с динамически добавленным элементом HTML

Я хочу привязать событие onclick к элементу, который я вставляю динамически с помощью jQuery

Но он никогда не запускает связанную функцию. Я был бы счастлив, если бы вы могли указать, почему этот пример не работает и как я могу заставить его работать правильно:

<!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" xml:lang="da" lang="da">
        <head>
          <title>test of click binding</title>

<script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
          <script type="text/javascript">


        jQuery(function(){
          close_link = $('<a class="" href="#">Click here to see an alert</a>');
          close_link.bind("click", function(){
            alert('hello from binded function call');
            //do stuff here...
          });
  
          $('.add_to_this').append(close_link);
        });
          </script>
        </head>
        <body>
          <h1 >Test of click binding</h1>
          <p>problem: to bind a click event to an element I append via JQuery.</p>

          <div class="add_to_this">
            <p>The link is created, then added here below:</p>
          </div>

          <div class="add_to_this">
            <p>Another is added here below:</p>
          </div>


        </body>
        </html>

Ответ 1

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

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

function handler() { alert('hello'); }
$('.add_to_this').append(function() {
  return $('<a>Click here</a>').click(handler);
})

Другая потенциальная проблема может заключаться в том, что наблюдатель событий прикреплен до того, как элемент был добавлен в DOM. Я не уверен, что это может что-то сказать, но я думаю, что поведение можно считать неопределенным. Более надежный подход, вероятно, будет:

function handler() { alert('hello'); }
$('.add_to_this').each(function() {
  var link = $('<a>Click here</a>');
  $(this).append(link);
  link.click(handler);
});

Ответ 2

Все эти методы устарели. Вы должны использовать метод on для решения вашей проблемы.

Если вы хотите настроить динамически добавленный элемент, вам нужно будет использовать

$(document).on('click', selector-to-your-element , function() {
     //code here ....
});

это заменит устаревший метод .live().

Ответ 3

Как насчет метода Live?

$('.add_to_this a').live('click', function() {
    alert('hello from binded function call');
});

Тем не менее, то, что вы сделали, похоже, должно работать. Там другое сообщение, которое выглядит довольно похоже.

Ответ 4

Немного поздно, но я подумал, что попытаюсь прояснить некоторые распространенные заблуждения в обработчиках событий jQuery. Начиная с jQuery 1.7, вместо устаревшего .live() следует использовать .on(), чтобы делегировать обработчики событий на элементы, которые динамически создаются в любой момент после назначения обработчика события.

Тем не менее, это не просто переключение live для on, потому что синтаксис несколько отличается:

Новый метод (пример 1):

$(document).on('click', '#someting', function(){

});

Устаревший метод (пример 2):

$('#something').live(function(){

});

Как показано выше, существует разница. Твист .on() действительно можно назвать похожим на .live(), передав селектор самой функции jQuery:

Пример 3:

$('#something').on('click', function(){

});

Однако, не используя $(document), как в примере 1, пример 3 не будет работать для динамически создаваемых элементов. Пример 3 абсолютно подходит, если вам не требуется динамическое делегирование.

Должен ли $(document).on() использоваться для всего?

Он будет работать, но если вам не требуется динамическое делегирование, было бы более целесообразно использовать пример 3, потому что пример 1 требует немного больше работы из браузера. Не будет никакого реального влияния на производительность, но имеет смысл использовать наиболее подходящий метод для вашего использования.

Должен ли использоваться .on() вместо .click(), если динамическое делегирование не требуется?

Не обязательно. Ниже приведен только ярлык, например, 3:

$('#something').click(function(){

});

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

Литература:

Ответ 5

Рассмотрим это:

jQuery(function(){
  var close_link = $('<a class="" href="#">Click here to see an alert</a>');
      $('.add_to_this').append(close_link);
      $('.add_to_this').children().each(function()
      {
        $(this).click(function() {
            alert('hello from binded function call');
            //do stuff here...
        });
      });
});

Он будет работать, потому что вы прикрепляете его к каждому конкретному элементу. Вот почему вам нужно - после добавления вашей ссылки на DOM - найти способ явно выбрать ваш добавленный элемент как элемент JQuery в DOM и связать событие click с ним.

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

Ответ 6

Я считаю, что это хороший способ:

$('#id').append('<a id="#subid" href="#">...</a>');
$('#subid').click( close_link );

Ответ 7

Возможно, и иногда необходимо создать событие click вместе с элементом. Это, например, когда привязка на основе селектора не является опцией. Основная часть заключается в том, чтобы избежать проблемы, о которой говорил Тобиас, используя .replaceWith() для одного элемента. Обратите внимание, что это всего лишь доказательство концепции.

<script>
    // This simulates the object to handle
    var staticObj = [
        { ID: '1', Name: 'Foo' },
        { ID: '2', Name: 'Foo' },
        { ID: '3', Name: 'Foo' }
    ];
    staticObj[1].children = [
        { ID: 'a', Name: 'Bar' },
        { ID: 'b', Name: 'Bar' },
        { ID: 'c', Name: 'Bar' }
    ];
    staticObj[1].children[1].children = [
        { ID: 'x', Name: 'Baz' },
        { ID: 'y', Name: 'Baz' }
    ];

    // This is the object-to-html-element function handler with recursion
    var handleItem = function( item ) {
        var ul, li = $("<li>" + item.ID + " " + item.Name + "</li>");

        if(typeof item.children !== 'undefined') {
            ul = $("<ul />");
            for (var i = 0; i < item.children.length; i++) {
                ul.append(handleItem(item.children[i]));
            }
            li.append(ul);
        }

        // This click handler actually does work
        li.click(function(e) {
            alert(item.Name);
            e.stopPropagation();
        });
        return li;
    };

    // Wait for the dom instead of an ajax call or whatever
    $(function() {
        var ul = $("<ul />");

        for (var i = 0; i < staticObj.length; i++) {
            ul.append(handleItem(staticObj[i]));
        }

        // Here; this works.
        $('#something').replaceWith(ul);
    });
</script>
<div id="something">Magical ponies ♥</div>

Ответ 8

    function load_tpl(selected=""){
        $("#load_tpl").empty();
        for(x in ds_tpl){
            $("#load_tpl").append('<li><a id="'+ds_tpl[x]+'" href="#" >'+ds_tpl[x]+'</a></li>');
        }
        $.each($("#load_tpl a"),function(){
            $(this).on("click",function(e){
                alert(e.target.id);
            });
        });
    }

Ответ 9

<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>    
<script>
    $(document).ready(function(){
        $(document).on('click', '.close', function(){
            var rowid='row'+this.id;
            var sl = '#tblData tr[id='+rowid+']';
            console.log(sl);
            $(sl).remove();
        });
        $("#addrow").click(function(){
            var row='';
            for(var i=0;i<10;i++){
                row=i;
                row='<tr id=row'+i+'>'
                    +   '<td>'+i+'</td>'
                    +   '<td>ID'+i+'</td>'
                    +   '<td>NAME'+i+'</td>'
                    +   '<td><input class=close type=button id='+i+' value=X></td>'
                    +'</tr>';
                console.log(row);
                $('#tblData tr:last').after(row);
            }
        });
    });

</script>
</head>
  <body>
    <br/><input type="button" id="addrow" value="Create Table"/>
    <table id="tblData" border="1" width="40%">
        <thead>
        <tr>
            <th>Sr</th>
            <th>ID</th>
            <th>Name</th>
            <th>Delete</th>
        </tr>
        </thead>
    </table>
    </body>
 </html>