Таблицы данных jQuery — щелчок по строке не регистрируется на страницах, отличных от первой

#javascript #jquery #events #datatables #jquery-events

#javascript #jquery #Мероприятия #таблицы данных #jquery-события

Вопрос:

Я использую плагин jQuery для таблиц данных и настраиваю обработчик щелчков при щелчке по строке следующим образом:

 $('#dt tbody tr').click(function () {
        alert('e');
});
  

Это отлично работает для первой страницы результатов DataTables.

Однако, когда я перехожу на другую страницу результатов, обработчик щелчков больше не регистрируется вообще.

Я предполагаю, что код DataTables останавливает передачу click события моему обработчику, но поскольку это происходит только на страницах после первой, это кажется необычным.

Таким образом, кто-нибудь:

  1. Столкнулся (и в идеале решил) с этой проблемой
  2. Найден хороший способ отслеживать распространение события jQuery / JS, чтобы определить причину остановки события

Приветствия

Комментарии:

1. Мое предположение было неверным. Еще одно невысказанное предположение: что привязка в ajaxComplete будет привязываться ко всем строкам, было недопустимым, поскольку DataTables является разумным и не отображает все строки в браузере до тех пор, пока это не потребуется. Таким образом, ответ Кона на live() правильный.

2. Пожалуйста, посмотрите на ответ, предоставленный Крисом Эвериттом. Он использует встроенную функцию DataTables и НЕ использует устаревшие функции jquery.

Ответ №1:

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

Проверьте функцию live() от jQuery. Ключевым моментом здесь является то, что обработчики событий привязаны ко всем элементам, удовлетворяющим критериям выбора «сейчас и в будущем».

Комментарии:

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

2. Это имеет смысл, если вы загружаете строки ДО определения обработчика click().

3. Конечно, я поместил click в свой ajaxComplete обработчик, думая, что DataTables загружает все строки и просто скрывает их. Однако это привязывается только к первой странице, потому что это все отображаемые таблицы данных (остальные хранятся в памяти). Это исправляет это $('#dt tbody tr').live('click', function () и т.д. (И фактически может быть объявлено вне ajaxComplete из-за упомянутого вами бита «сейчас и в будущем».

4. Просто отметим, что live () устарел, и теперь вместо него следует использовать on() (для jquery > 1.7). Смотрите api.jquery.com/on

5. для меня on (), похоже, не работает… Я просто заменяю вызов live () функцией on (), но это не работает… какие-либо предостережения?

Ответ №2:

У меня была эта проблема в одностраничном приложении. У меня метод live работал, за исключением обратной отправки. Моя таблица была заполнена с помощью ajax, и пользователь мог вызвать ее уничтожение и воссоздание.

Чтобы исправить это, я использовал DataTables.$: «http://datatables.net/api #$»

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

 $(document).ready(function() {
    /*
    * Insert a 'details' column to the table
    */
    var nCloneTh = document.createElement( 'th' );
    var nCloneTd = document.createElement( 'td' );
    nCloneTd.innerHTML = '<img src="../examples_support/details_open.png">';
    nCloneTd.className = "center";

    /* CHANGE: Remove all the expand control elements we may have added earlier
    * or else you'll add a new column for every postback
    */
    $('.expand-control').remove();

    /*
    * CHANGE: Add the expand-control class to these elements,
    * so we can remove them after a postback
    */
    $(nCloneTh).addClass('expand-control');
    $(nCloneTd).addClass('expand-control');

    $('#example thead tr').each( function () {
        this.insertBefore( nCloneTh, this.childNodes[0] );
    } );

    $('#example tbody tr').each( function () {
        this.insertBefore(  nCloneTd.cloneNode( true ), this.childNodes[0] );
    } );

    /*
    * Initialse DataTables, with no sorting on the 'details' column
    */
    var oTable = $('#example').dataTable( {
        "aoColumnDefs": [
            { "bSortable": false, "aTargets": [ 0 ] }
        ],
        "aaSorting": [[1, 'asc']]
    });

    /* Add event listener for opening and closing details
    * Note that the indicator for showing 
    * which row is open is not controlled by DataTables,
    * rather it is done here
    */

    /* CHANGE:  Here I use jQuery.dataTable.$ instead of
    * jQuery('#example tbody td img'),
    * this is what preserves the event handler on the 2nd (etc) 
    * pages after a postback
    * Note the use of on instead of live, recommended over live as of 1.7 
    */
    oTable.$('tr').find('img').on('click', function () {
        var nTr = $(this).parents('tr')[0];
        if ( oTable.fnIsOpen(nTr) )
        {
            /* This row is already open - close it */
            this.src = "../examples_support/details_open.png";
            oTable.fnClose( nTr );
        }
        else
        {
            /* Open this row */
            this.src = "../examples_support/details_close.png";
            oTable.fnOpen( nTr, fnFormatDetails(oTable, nTr), 'details' );
        }
    } );
} );
  

Комментарии:

1. Это должен быть принятый ответ. Использование устаревших функций, таких как jquery live(), никогда не является хорошей идеей. Просто используйте tableVariable.$(‘tr’) вместо $ (‘#tableId tr’), как вы сказали. 1

2. Это также решило мою аналогичную проблему при попытке использовать метод, предложенный в этом сообщении в блоге: ricardocovo.com/2010/09/02 /… (т. е. с использованием диалогового окна подтверждения удаления в сочетании с таблицами данных jQuery); … ссылки удаления перестали работать на страницах после первой страницы; поэтому вместо использования $ (‘delete-link’).click( функция () и т.д. … , Я использовал идею выше, чтобы исправить проблему, сказав: oTable.$(‘.delete-link’).on (‘click’, функция() { … }; в этот момент ссылки удаления снова начали работать.

Ответ №3:

У меня была такая же проблема с кнопками во всех строках моих таблиц данных, событие щелчка не сработало ни на одной кнопке после первой страницы результатов. Кон предоставил правильный анализ (спасибо, Кон), но для тех, кто ищет пример кода, вот что сработало для меня:

 $('.myButton').live('click', function() {
    var id = $(this).closest("tr").attr("id");
    var string = 'div_id='   id;
    alert(string);
       // string sent to processing script here
});
  

Надеюсь, это поможет!

Комментарии:

1. Спасибо. Код с ответом всегда полезен

Ответ №4:

Поскольку live теперь устарел, я предлагаю использовать ‘.on’.

Это должно решить вашу проблему:

 $(document).on('click', '.myButton', function() {
    var id = $(this).closest("tr").attr("id");
    var string = 'div_id='   id;
    alert(string);
       // string sent to processing script here
});
  

Вы можете обменять документ на какой-либо родительский элемент, поскольку это не очень эффективно. Возможно, попробуйте использовать div, содержащий вашу таблицу.

Ответ №5:

Мой ответ похож на ответ @Chris Everitt, с небольшим отличием. Просто для тех, кто хотел бы это увидеть .. вот оно..

  var oTable = $('#masterTable').dataTable( {

                "aLengthMenu": [[5,10, 25, 50, 100 , -1], [5,10, 25, 50, 100, "All"]],
                "iDisplayLength" : 10,
                "aoColumnDefs": [
                             {"sWidth": "25%", "aTargets": [ 0 ] },
                             {"sWidth": "10%", "aTargets": [ 1 ] },
                             {"sWidth": "10%", "aTargets": [ 2 ] },
                             {"sWidth": "10%", "aTargets": [ 3 ] },
                             {"sWidth": "10%", "aTargets": [ 4 ] },
                             {"sWidth": "10%", "aTargets": [ 5 ] },
                             {"sWidth": "15%", "aTargets": [ 6 ] },

                             {"sClass": "align-left" , "aTargets": [ 0,1,4, 2,3,5,6] }              
                         ],

            "aoColumns": [
              { "bSortable": true },
              null, null, null,null, null, 
              { "bSortable": true }
            ]

            });
  

Событие регистрации для всех изображений (dom attr) в таблице —

  oTable.$('td').each( function () {

                    $(this).on('click','img', function () {
                        var nTr = $(this).parents('tr')[0];
                        if ( oTable.fnIsOpen(nTr) )
                        {
                            /* This row is already open - close it */
                            this.src = "${pageContext.request.contextPath}/theme/v_1_0/app-images/details_open.png";
                            oTable.fnClose( nTr );
                        }
                        else
                        {
                            /* Open this row */
                            this.src = "${pageContext.request.contextPath}/theme/v_1_0/app-images/details_close.png";



                            var html = '<div> Placeholder here.. </div>';

                            oTable.fnOpen(nTr, html, 'details');

                           }
                    } );