数据表:如何在 Ajax 重新加载后保持子行打开
Datatables: How can I keep child rows opened after the Ajax reload
我正在使用 Ajax 源来生成 table。这一个每 5000 毫秒刷新一次,当子行打开时,它会被 table 的重绘关闭。我怎样才能让这些打开?
我的代码:
/* Formatting function for row details - modify as you need */
function format ( d ) {
// `d` is the original data object for the row
return '<p>Text in child row</p>';
}
$(document).ready(function() {
$('#table').DataTable( {
...
} );
var tr;
var row;
$('#table tbody').on('click', 'td.details-control', function () {
if (tr !== null && tr !== undefined && row !== null && tr !== undefined) {
row.child.hide();
tr.removeClass('shown');
}
tr = $(this).closest('tr');
row = table.row( tr );
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
} );
$.fn.dataTable.ext.errMode = 'none';
var table = $('#table').DataTable();
setInterval( function () {
table.ajax.reload( function () {
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
if (tr.hasClass('shown')) {
// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
}
} );
}, 5000 );
$('table td .details-control').html('<button><i class="fa fa-plus"></i></button>');
} );
参考Child rows example and ajax.reload()方法。
- 经过一些研究,我发现人们建议在 jQuery
中使用 cookie
据我所知,您正在用来自 ajax 的数据创建的新 table 清除之前的 table。
您将必须保存打开的行的状态,并且每当您完成刷新时 table 使用保存的状态展开行。
要回答最初的问题(如何在 DataTable AJAX 重新加载时保持子行打开),请参阅以下实现。
我使用 cookie 来保持子行打开,我正在使用 js-cookie
找到的插件 here。
最好将唯一标识符作为 table 的列,以便 re-opened 行是正确的。
$(function(){
var dt = $('#my_table').DataTable(...);
var reloadInterval = 10000; // milliseconds
// Add extra-info row
dt_add_details('my_table', 'details-control', formatCallback, 'id');
var reloadCallback = function(json){
dt_reopen_rows('my_table', formatCallback, 'id')
};
// Reload AJAX source every X seconds
setInterval(function(){
dt.ajax.reload(reloadCallback, false);
}, reloadInterval)
});
/**
* Format child row data.
*/
function formatCallback(d){
...
}
/**
* Show / Hide extra-info when clicking on the column identified by className.
* @param {String} selector - The HTML selector for the table.
* @param {String} className - The column class name that holds the extra-info.
* @param {Function} formatCallback - Function used to format the data of the
* child row.
* @param {String} cookieDataIndex - The data index to keep in cookie.
*/
function dt_add_details(selector, className, formatCallback, cookieDataIndex){
$(selector + ' tbody').on('click', 'td.' + className, function () {
var ckey = 'openRows_' + selector;
var openRows = Cookies.getJSON(ckey);
// Create cookie if never created
if (typeof openRows == 'undefined'){
Cookies.set(ckey, [], {'path': ''});
var openRows = Cookies.getJSON(ckey);
};
// Get current info
var tr = $(this).closest('tr');
var row = $(selector).DataTable().row(tr);
var id = row.data()[cookieDataIndex];
if (row.child.isShown()){
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
// Remove opened row from cookie
var idx = openRows.indexOf(id);
openRows.splice(idx, 1);
Cookies.set(ckey, openRows, {path: ''});
}
else{
// Open this row
row.child(formatCallback(row.data())).show();
tr.addClass('shown');
// Add row 'id' field to cookie
if (openRows.indexOf(id) < 0){
openRows.push(id);
}
Cookies.set(ckey, openRows, {path: ''});
}
// console.log("Opened rows: " + Cookies.getJSON('openRows_' + selector))
});
}
/**
* Show / Hide extra-info when clicking on the column identified by className.
* @param {String} selector - The HTML selector for the table.
* @param {Function} formatCallback - Function used to format the data of the
* the child row.
* @param {String} cookieDataIndex - The data index to keep in cookie.
*/
function dt_reopen_rows(selector, formatCallback, cookieDataIndex) {
var ckey = 'openRows_' + selector;
var openRows = Cookies.getJSON(ckey);
if (!openRows)
return;
var table = $(selector).DataTable(); // existing DataTable
$(table.rows().nodes()).each(function (idx, tr) {
var row = table.row(tr);
var id = row.data()[cookieDataIndex]
if (openRows.indexOf(id) >= 0) {
// console.log("Id " + id + " found in previously opened row. Re-opening.")
$(tr).addClass("shown");
row.child(formatCallback(row.data())).show();
}
});
}
使用此解决方案,table 中的每一行都应该有一个行 ID。有关详细信息,请参阅:https://datatables.net/reference/option/rowId
HTML
<script src="http://code.jquery.com/jquery-latest.min.js"
type="text/javascript"></script>
<link rel="stylesheet" type="text/css"
href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
table id="example" class="display" style="width:100%">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</tfoot>
</table>
Javascript
/* Function to create a new row, fell free to render your code here */
function format(d) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">' +
'<tr>' +
'<td>Full name:</td>' +
'<td>' + d.name + '</td>' +
'</tr>' +
'<tr>' +
'<td>Extension number:</td>' +
'<td>' + d.extn + '</td>' +
'</tr>' +
'<tr>' +
'<td>Extra info:</td>' +
'<td>And any further details here (images etc)...</td>' +
'</tr>' +
'</table>';
}
function onClickEventListener() {
var tr = $(this).closest('tr');
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child(format(row.data())).show();
tr.addClass('shown');
}
let currentRowID = "#" + ($(this).closest('tr').attr('id'));
if ($.inArray(currentRowID, rowIds) !== -1) {
//Row is closed, remove row ID from rowIDs array
var index = rowIds.indexOf(currentRowID);
if (index !== -1) rowIds.splice(index, 1);
rowIds.filter(function (val) {
return val
});
} else {
//Row is opened, add row ID to rowIDs array
rowIds.push(currentRowID);
}
}
$(document).ready(function () {
let rowIds = [];
var table = $('#example').DataTable({
"ajax": "{{ path('your_data_source') }}",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{"data": "name"},
{"data": "position"},
{"data": "office"},
{"data": "salary"}
],
"order": [[1, 'asc']]
});
// Add event listener for opening and closing the row
$('#example tbody').on('click', 'td.details-control', onClickEventListener);
//set interval to update datatable
setInterval(function () {
table.ajax.reload(function () {
//Iterate through all the open rows and open them again <--Value is set in the onClickEventListener function
table.rows(rowIds).every(function (row, index, array) {
table.row(row).child(format(this.data())).show();
this.nodes().to$().addClass('shown');
//Add a minus icon for the open row
this.nodes().to$().children('td:first').html('<img style="max-width: 30px;; max-height: 100%;object-fit: contain" src=' + '{{ asset('img/datatables/icon_minus.png') }}' + ' ></img>');
});
//Set to false if you don't want the paging to reset after ajax load,otherwise true
}, false);
}, 1000);
});
尝试存储打开的行的索引值(全局)
table重新加载后,调用如下方法
function openChildByIndex(){
let row = table.row('globally stored index'); //place your index here
row.child(format(row.data())).show();
$(row.node()).addClass('shown');
}
我正在使用 Ajax 源来生成 table。这一个每 5000 毫秒刷新一次,当子行打开时,它会被 table 的重绘关闭。我怎样才能让这些打开?
我的代码:
/* Formatting function for row details - modify as you need */
function format ( d ) {
// `d` is the original data object for the row
return '<p>Text in child row</p>';
}
$(document).ready(function() {
$('#table').DataTable( {
...
} );
var tr;
var row;
$('#table tbody').on('click', 'td.details-control', function () {
if (tr !== null && tr !== undefined && row !== null && tr !== undefined) {
row.child.hide();
tr.removeClass('shown');
}
tr = $(this).closest('tr');
row = table.row( tr );
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
} );
$.fn.dataTable.ext.errMode = 'none';
var table = $('#table').DataTable();
setInterval( function () {
table.ajax.reload( function () {
if ( row.child.isShown() ) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
if (tr.hasClass('shown')) {
// Open this row
row.child( format(row.data()) ).show();
tr.addClass('shown');
}
}
} );
}, 5000 );
$('table td .details-control').html('<button><i class="fa fa-plus"></i></button>');
} );
参考Child rows example and ajax.reload()方法。
- 经过一些研究,我发现人们建议在 jQuery 中使用 cookie
据我所知,您正在用来自 ajax 的数据创建的新 table 清除之前的 table。 您将必须保存打开的行的状态,并且每当您完成刷新时 table 使用保存的状态展开行。
要回答最初的问题(如何在 DataTable AJAX 重新加载时保持子行打开),请参阅以下实现。
我使用 cookie 来保持子行打开,我正在使用 js-cookie
找到的插件 here。
最好将唯一标识符作为 table 的列,以便 re-opened 行是正确的。
$(function(){
var dt = $('#my_table').DataTable(...);
var reloadInterval = 10000; // milliseconds
// Add extra-info row
dt_add_details('my_table', 'details-control', formatCallback, 'id');
var reloadCallback = function(json){
dt_reopen_rows('my_table', formatCallback, 'id')
};
// Reload AJAX source every X seconds
setInterval(function(){
dt.ajax.reload(reloadCallback, false);
}, reloadInterval)
});
/**
* Format child row data.
*/
function formatCallback(d){
...
}
/**
* Show / Hide extra-info when clicking on the column identified by className.
* @param {String} selector - The HTML selector for the table.
* @param {String} className - The column class name that holds the extra-info.
* @param {Function} formatCallback - Function used to format the data of the
* child row.
* @param {String} cookieDataIndex - The data index to keep in cookie.
*/
function dt_add_details(selector, className, formatCallback, cookieDataIndex){
$(selector + ' tbody').on('click', 'td.' + className, function () {
var ckey = 'openRows_' + selector;
var openRows = Cookies.getJSON(ckey);
// Create cookie if never created
if (typeof openRows == 'undefined'){
Cookies.set(ckey, [], {'path': ''});
var openRows = Cookies.getJSON(ckey);
};
// Get current info
var tr = $(this).closest('tr');
var row = $(selector).DataTable().row(tr);
var id = row.data()[cookieDataIndex];
if (row.child.isShown()){
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
// Remove opened row from cookie
var idx = openRows.indexOf(id);
openRows.splice(idx, 1);
Cookies.set(ckey, openRows, {path: ''});
}
else{
// Open this row
row.child(formatCallback(row.data())).show();
tr.addClass('shown');
// Add row 'id' field to cookie
if (openRows.indexOf(id) < 0){
openRows.push(id);
}
Cookies.set(ckey, openRows, {path: ''});
}
// console.log("Opened rows: " + Cookies.getJSON('openRows_' + selector))
});
}
/**
* Show / Hide extra-info when clicking on the column identified by className.
* @param {String} selector - The HTML selector for the table.
* @param {Function} formatCallback - Function used to format the data of the
* the child row.
* @param {String} cookieDataIndex - The data index to keep in cookie.
*/
function dt_reopen_rows(selector, formatCallback, cookieDataIndex) {
var ckey = 'openRows_' + selector;
var openRows = Cookies.getJSON(ckey);
if (!openRows)
return;
var table = $(selector).DataTable(); // existing DataTable
$(table.rows().nodes()).each(function (idx, tr) {
var row = table.row(tr);
var id = row.data()[cookieDataIndex]
if (openRows.indexOf(id) >= 0) {
// console.log("Id " + id + " found in previously opened row. Re-opening.")
$(tr).addClass("shown");
row.child(formatCallback(row.data())).show();
}
});
}
使用此解决方案,table 中的每一行都应该有一个行 ID。有关详细信息,请参阅:https://datatables.net/reference/option/rowId
HTML
<script src="http://code.jquery.com/jquery-latest.min.js"
type="text/javascript"></script>
<link rel="stylesheet" type="text/css"
href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
table id="example" class="display" style="width:100%">
<thead>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</thead>
<tfoot>
<tr>
<th></th>
<th>Name</th>
<th>Position</th>
<th>Office</th>
<th>Salary</th>
</tr>
</tfoot>
</table>
Javascript
/* Function to create a new row, fell free to render your code here */
function format(d) {
// `d` is the original data object for the row
return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">' +
'<tr>' +
'<td>Full name:</td>' +
'<td>' + d.name + '</td>' +
'</tr>' +
'<tr>' +
'<td>Extension number:</td>' +
'<td>' + d.extn + '</td>' +
'</tr>' +
'<tr>' +
'<td>Extra info:</td>' +
'<td>And any further details here (images etc)...</td>' +
'</tr>' +
'</table>';
}
function onClickEventListener() {
var tr = $(this).closest('tr');
var row = table.row(tr);
if (row.child.isShown()) {
// This row is already open - close it
row.child.hide();
tr.removeClass('shown');
}
else {
// Open this row
row.child(format(row.data())).show();
tr.addClass('shown');
}
let currentRowID = "#" + ($(this).closest('tr').attr('id'));
if ($.inArray(currentRowID, rowIds) !== -1) {
//Row is closed, remove row ID from rowIDs array
var index = rowIds.indexOf(currentRowID);
if (index !== -1) rowIds.splice(index, 1);
rowIds.filter(function (val) {
return val
});
} else {
//Row is opened, add row ID to rowIDs array
rowIds.push(currentRowID);
}
}
$(document).ready(function () {
let rowIds = [];
var table = $('#example').DataTable({
"ajax": "{{ path('your_data_source') }}",
"columns": [
{
"className": 'details-control',
"orderable": false,
"data": null,
"defaultContent": ''
},
{"data": "name"},
{"data": "position"},
{"data": "office"},
{"data": "salary"}
],
"order": [[1, 'asc']]
});
// Add event listener for opening and closing the row
$('#example tbody').on('click', 'td.details-control', onClickEventListener);
//set interval to update datatable
setInterval(function () {
table.ajax.reload(function () {
//Iterate through all the open rows and open them again <--Value is set in the onClickEventListener function
table.rows(rowIds).every(function (row, index, array) {
table.row(row).child(format(this.data())).show();
this.nodes().to$().addClass('shown');
//Add a minus icon for the open row
this.nodes().to$().children('td:first').html('<img style="max-width: 30px;; max-height: 100%;object-fit: contain" src=' + '{{ asset('img/datatables/icon_minus.png') }}' + ' ></img>');
});
//Set to false if you don't want the paging to reset after ajax load,otherwise true
}, false);
}, 1000);
});
尝试存储打开的行的索引值(全局)
table重新加载后,调用如下方法
function openChildByIndex(){
let row = table.row('globally stored index'); //place your index here
row.child(format(row.data())).show();
$(row.node()).addClass('shown');
}