jQuery DataTables - выбор строки не регистрируется на страницах, кроме первого

17

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

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

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

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

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

Как таковой, есть кто-нибудь:

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

Приветствия     

задан Matt Mitchell 13.05.2011 в 01:56
источник
  • Моя презумпция неверна. Еще одна неустановленная презумпция: привязка в ajaxComplete будет привязана ко всем строкам, была недействительной, поскольку DataTables является мудрым и не отображает все строки в браузере до тех пор, пока это не понадобится. Таким образом, ответ Конна live () правильный. –  Matt Mitchell 13.05.2011 в 02:08
  • Пожалуйста, посмотрите на ответ, предоставленный Крисом Эвереттом. Он использует встроенную функцию DataTables и НЕ использует устаревшие функции jquery. –  Nullius 16.07.2013 в 14:13

5 ответов

11

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

Чтобы исправить это, я использовал dataTables. $: "Http://datatables.net/api#$"

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

$(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' );
        }
    } );
} );
    
ответ дан Chris Everitt 04.12.2012 в 16:44
  • Это должен быть принятый ответ. Использование устаревших функций, таких как jquery live (), никогда не является хорошей идеей. Просто используйте tableVariable. $ ('Tr') вместо $ ('# tableId tr'), как вы сказали. +1 –  Nullius 16.07.2013 в 14:12
  • Обновлено, спасибо. –  Matt Mitchell 17.07.2013 в 06:16
  • Это также решило мою аналогичную проблему при попытке использовать технику, предложенную в этом блоге: ricardocovo.com/2010/09/02/... (т. е. используя метод диалога подтверждения удаления в сочетании с jQuery datatables); ... ссылки удаления перестали работать на страницах после первой страницы; поэтому вместо того, чтобы использовать $ ('delete-link'). click (function () и т. д.), я использовал вышеприведенную идею, чтобы исправить эту проблему, указав: oTable. $ ('. delete-link'). on ( 'click', function () {...}; в этот момент ссылки на удаление снова начали работать. –  David Barrows 12.08.2013 в 14:45
12

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

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

    
ответ дан Kon 13.05.2011 в 01:59
  • Право, конечно, приветствия. Странно, что он работал на первой странице (все строки загружаются динамически), но, тем не менее, я думаю, что это ответ. Вскоре я подтвержу и соглашусь. –  Matt Mitchell 13.05.2011 в 02:01
  • Это имеет смысл, если вы загружаете строки ПЕРЕД определением обработчика click (). –  Kon 13.05.2011 в 02:02
  • Конечно - я нажал на мой обработчик ajaxComplete, думая, что DataTables загружает все строки и просто скрывает их. Однако это относится только к первой странице, потому что это все данные DataTables (остальные хранятся в памяти). Это означает, что это означает, что это означает, что он работает в режиме ожидания ('# dt tbody tr'). Live ('click', function () и т. Д. Исправляет его (и фактически может быть объявлен за пределами ajaxComplete из-за битва «сейчас и в будущем». –  Matt Mitchell 13.05.2011 в 02:03
  • Просто обратите внимание, что live () устарел, и теперь вы должны использовать вместо него () для jQuery> 1.7. См. Api.jquery.com/on –  khylo 01.05.2012 в 18:42
  • для меня on (), похоже, не работает ... Я просто заменю вызов live () с функцией on (), но он не работает ... какие-либо оговорки? –  Rohit Banga 05.10.2012 в 16:43
5

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

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

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

ответ дан BD_Design 21.04.2012 в 10:04
  • Спасибо. Код с ответом всегда полезен –  bladefist 30.04.2012 в 07:43
  • благодарит работает отлично! попробовал. но он не сработал. –  rashid 16.11.2013 в 10:48
3

Так как 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
});

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

    
ответ дан Ken Johnson 30.08.2013 в 21:33
1

Мой ответ подобен тому, что у @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 }
            ]

            });

Регистрация события для всех img (dom attr's) в таблице -

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

                           }
                    } );    
    
ответ дан Sirish 23.04.2014 в 21:25