Событие JQuery не будет срабатывать после вызова ajax

Это довольно странная проблема с jquery. Я загружаю div

<div id="container">

при загрузке страницы. Каждая запись представляет собой табличные данные с ассоциированной с ним функцией "удалить" ajax. Когда страница загружается и нажимает ссылку "удалить", вызов ajax срабатывает просто отлично. Однако, как только событие запущено, данные возвращаются из вызова ajax, а div заполняется данными (но страница не обновляется или не перезагружается) Когда я снова нажимаю ссылку, ajax script не будет запускаться. Вот мой код:

$(document).ready(function() {
    $("button.done").button({
    }).click(function() {
        var BatchID = $("input#BatchID").val();
        var Amount = $("input#Amount").val();
        var Name = $("input#CheckName").val();
        var Check_Number = $("input#Check_Number").val();
        var Company = $("select#Company").val();
        var Department = $("select#Department").val();
        $.ajax({
            type: 'GET',
            url: '/app/usagCheckEntryWS.html',
            data: {
                "BatchID" : BatchID,
                "Amount" : Amount,
                "Name" : Name,
                "Check_Number" : Check_Number,
                "Company" : Company,
                "Department" : Department
            },
            success: function (data) {
                    var ang = '';
                    var obj = $.parseJSON(data);
                    $.each(obj, function() {
                       ang += '<table><tr><td width="45">' + this["RefID"] + '</td><td width="140">' + this["Name"] + '</td><td width="95">' + this["CheckNumber"] + '</td><td align="right" width="70">$' + this["Amount"] + '</td><td width="220" style="padding-left: 15px;">' + this["Description"] + '</td><td><div class="delete" rel="' + this["RefID"] + '"><span>Delete</span></div></td></tr></table>';
                    });
                    $('#container').html(ang);
                    $("input#Amount").val('');
                    $("input#CheckName").val('');
                    $("input#Check_Number").val('');
                    $("select#Company").val('MMS');
                    $("th#dept").hide();
                    $('input#CheckName').focus();
            }
        });
    });
});

Ответ 1

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

(Это также относится к содержимому, добавленному на страницу после загрузки страницы, то есть к загружаемому содержимому ajax)

Для этого существует несколько возможных решений.

1) Инкапсулируйте свой "привязывающий" код и вызовите его как при загрузке страницы, так и сразу после того, как элемент, о котором идет речь, будет добавлен обратно на страницу. Например:

$(document).ready(function(){
    // bind event handlers when the page loads.
    bindButtonClick();
});

function bindButtonClick(){
    $('.myClickableElement').click(function(){
        ... event handler code ...
    });
}

function updateContent(){
    $.ajax({
        url : '/ajax-endpoint.php',
        data : {'onMyWay' : 'toServer'},
        dataType : 'html',
        type : 'post',
        success : function(responseHtml){
            // .myClickableElement is replaced with new (unbound) html element(s)
            $('#container').html(responseHtml);

            // re-bind event handlers to '.myClickableElement'
            bindButtonClick();  
        }
    });
}

2) Более элегантный способ справиться с этим: используйте метод jQuery.on(). С его помощью вы можете привязывать обработчики событий к элементам, отличным от цели события, т.е. К элементу, который никогда не удаляется со страницы.

$(document).ready(function(){
    $('body').on('click','.myClickableElement',function(){
        ... event handler code ....
    });
});

Некоторые дополнительные пояснения:

В методе .on() используется делегирование событий, чтобы сообщить родительскому элементу сохранить код обработчика событий (3-й аргумент) и запускать его, когда объект (2-й аргумент) имеет определенный тип события (1-й аргумент), выполненный на нем.

Если вы используете версию jQuery до 1.7, используйте теперь устаревший метод delegate, который по сути делает то же самое.

Кроме того, стоит отметить, что из-за того, как события "пузырятся" через дерево dom, цель события (второй аргумент метода .on()) должна быть потомком делегирующего элемента (селектор объектов jQuery), Например, следующее НЕ будет работать

<div id="container-1">
    <div>
        <div id="another-div">
            Some Stuff
        </div>
    </div>
</div>

<div id="container-2">
    <a id="click-me">Event Target!!!</a>
</div>

<script type="text/javascript">
    $('#container-1').on('click','#click-me',function(){
        ... event handler code ....
    });
</script>

Элементы body или document обычно являются безопасными, поскольку обычно каждый элемент на странице является потомком.

Ответ 2

Вы можете заключить событие script в DIV и запустить команду Replaceall после динамической загрузки содержимого.

<div class="somescript">
-- Event Script that you want to map with dnamically added content
<div>

- динамически загружать ваш контент и запускать следующую команду после него.

$(".somescript").replaceAll($(".somescript"));

После загрузки динамически загруженного содержимого и выполнения команды замены события будут отображаться и код будет работать нормально.