服务器端模式下通过索引获取Datatables行数据失败求助
我负责验证用户点击Datatables行触发的弹窗输入数据,用户提交数据后由规则引擎执行QA校验,再将错误或警告返回至弹窗。目前需通过行索引获取对应数据以唤起正确弹窗,但尝试多种table.row(index)写法均返回undefined,仅通过节点获取数据正常。
相关代码如下:
(function($) { var agencyFactorsTable; ABC.page.init = function(options) { agencyFactorsTable = $('#agencyFactorsTable').DataTable({ columnDefs: [ { "type": "string", "targets": [ options.groupColumnsSize, options.groupColumnsSize + 4, options.groupColumnsSize + 6, options.groupColumnsSize + 7], render: function(data, type, full, meta){ if (type === 'filter' || type === 'sort') { var api = new $.fn.dataTable.Api(meta.settings); var td = api.cell({row: meta.row, column: meta.col}).node(); data = $('select, input[type="text"]', td).val(); } return data; } } ], "bJQueryUI": true, "bSortClasses": false, "sPaginationType": "full_numbers", "aaSorting": options.defaultOrder, "bAutoWidth": false, "bFilter": true, "iDisplayLength": 10, "dom": '<"H"lrM><"dataTables_scroll"t><"F"ipE>', "columns" : options.columns, "oLanguage": EIS.settings.dataTablesLanguage, "bProcessing": true, "processing": true, "bServerSide": true, "serverSide": true, "scrollX": true, "scrollY": true, "sInfo": "Showing _START_ to _TOTAL_ entries", "ajaxSource": options.templateDataUrl, "ajax": { "url": options.templateDataUrl, "dataSrc": "aaData" } }); $("#dialog-edit").dialog({ autoOpen: false, modal: true, width: 760, height: 500, buttons: [] }); agencyFactorsTable.on('click', 'tbody tr td img.edit_dialog', function() { showPopup(this.parentNode); }); function showPopup(selectedNode) { var $source = agencyFactorsTable; var data; if (options.selectedRowId != null) { // set the index hidden field $("#selectedRowId").val(options.selectedRowId); // get the data by index, this does not work, I get "undefined" for the value of data data = agencyFactorsTable.row(options.selectedRowId).data(); // data = undefined // data = agencyFactorsTable.row(options.selectedRowId); // data = _Api {0: Array{1}, length: 1, selector ... <- this is not what I want, I want the array // data = $source.row(options.selectedRowId).data(); // data = undefined // data = $source.row(options.selectedRowId); // data = _Api {0: Array{1}, length: 1, selector ... <- this is not what I want, I want the array } else { // set hidden field value for selected row index, to pass back to server $("#selectedRowId").val($source.row(selectedNode).index()); // get the data by selected node, set above data = $source.row(selectedNode).data(); // data = Array(18) <- this is correct } $('#dialog-edit').dialog('open'); return false; }; if (options.selectedRowId != null) { showPopup(); }; }; })(jQuery);
问题原因及解决方法
核心原因:服务器端分页模式的限制
你的DataTables开启了serverSide: true(服务器端模式),这种模式下,DataTables只会加载当前页面的行数据到客户端内存中。row(index)方法接收的index参数是当前页内的本地行索引(从0开始),而非全局的行ID或服务器端返回的行序号。如果options.selectedRowId是服务器端的唯一ID或者全局行号,直接用它作为参数调用row(index)自然找不到对应行,返回undefined。
解决方法1:通过行唯一ID匹配数据(推荐)
如果服务器返回的每条行数据中包含唯一标识字段(比如id),可以通过自定义匹配函数定位目标行:
// 假设行数据中包含id字段,options.selectedRowId是该字段的值 data = agencyFactorsTable.row(function(idx, rowData, node) { return rowData.id === options.selectedRowId; }).data();
解决方法2:确认index为当前页的本地索引
如果options.selectedRowId确实是客户端本地的行索引,需要确保它属于当前加载页面的索引范围。服务器端模式下,当前页的行索引范围是[start, start+length-1](start为当前页起始的全局索引,length为每页条数),超出这个范围的索引会导致row(index)返回undefined。
节点方式有效的原因
通过$source.row(selectedNode).data()能正常获取数据,是因为该节点是当前DOM中存在的元素,DataTables可以直接关联到对应的客户端数据,不受服务器端分页的限制。
内容的提问来源于stack exchange,提问作者Paul

