DataTables+Datepicker 按日期范围过滤表格
Posted
技术标签:
【中文标题】DataTables+Datepicker 按日期范围过滤表格【英文标题】:DataTables+Datepicker filter table by date range 【发布时间】:2019-07-08 13:38:59 【问题描述】:尝试使用两个有界日期选择器按日期范围实现 DataTables 过滤器。
我在 SO 上看到的类似问题很少,但没有一个对我有用。
到目前为止,我设法实现了界面元素,但不知道如何将它们组合在一起以进一步进行。任何帮助表示赞赏。
var myTableData =
[
"id": "1",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2011/04/25",
"office": "Edinburgh",
"extn": "5421"
,
"id": "2",
"name": "Garrett Winters",
"position": "Accountant",
"salary": "$170,750",
"start_date": "2011/07/25",
"office": "Tokyo",
"extn": "8422"
,
"id": "3",
"name": "Ashton Cox",
"position": "Junior Technical Author",
"salary": "$86,000",
"start_date": "2009/01/12",
"office": "San Francisco",
"extn": "1562"
,
"id": "4",
"name": "Cedric Kelly",
"position": "Senior javascript Developer",
"salary": "$433,060",
"start_date": "2012/03/29",
"office": "Edinburgh",
"extn": "6224"
,
"id": "5",
"name": "Airi Satou",
"position": "Accountant",
"salary": "$162,700",
"start_date": "2008/11/28",
"office": "Tokyo",
"extn": "5407"
,
"id": "6",
"name": "Brielle Williamson",
"position": "Integration Specialist",
"salary": "$372,000",
"start_date": "2012/12/02",
"office": "New York",
"extn": "4804"
,
"id": "7",
"name": "Herrod Chandler",
"position": "Sales Assistant",
"salary": "$137,500",
"start_date": "2012/08/06",
"office": "San Francisco",
"extn": "9608"
];
$('.datepicker').datepicker();
var myDataTable = $('#staff').DataTable(
sDom: 't',
data: myTableData,
columns: [
title: 'Name', data: 'name',
title: 'Position', data: 'position',
title: 'Office', data: 'office',
title: 'Hire date', data: 'start_date',
title: 'Salary', data: 'salary'
]
);
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
</head>
<body>
<label>Start date:</label>
<input id="startdate" class="datepicker"></input>
<label>End date:</label>
<input id="enddate" class="datepicker"></input>
<button id="filter">Filter</button>
<table id="staff"></table>
</body>
</html>
【问题讨论】:
【参考方案1】:我对您的代码做了一些修改。请参阅下面 JavaScript sn-p 中的 cmets,其中大部分位于底部,在您的 var myDataTable = $('#staff').DataTable()
声明下:
// I changed some of the start_date values to be more recent, just for testing.
var myTableData = [
"id": "1",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2017/04/25",
"office": "Edinburgh",
"extn": "5421"
,
"id": "2",
"name": "Garrett Winters",
"position": "Accountant",
"salary": "$170,750",
"start_date": "2018/07/25",
"office": "Tokyo",
"extn": "8422"
,
"id": "3",
"name": "Ashton Cox",
"position": "Junior Technical Author",
"salary": "$86,000",
"start_date": "2019/01/12",
"office": "San Francisco",
"extn": "1562"
,
"id": "4",
"name": "Cedric Kelly",
"position": "Senior Javascript Developer",
"salary": "$433,060",
"start_date": "2018/03/29",
"office": "Edinburgh",
"extn": "6224"
,
"id": "5",
"name": "Airi Satou",
"position": "Accountant",
"salary": "$162,700",
"start_date": "2018/11/28",
"office": "Tokyo",
"extn": "5407"
,
"id": "6",
"name": "Brielle Williamson",
"position": "Integration Specialist",
"salary": "$372,000",
"start_date": "2018/12/02",
"office": "New York",
"extn": "4804"
,
"id": "7",
"name": "Herrod Chandler",
"position": "Sales Assistant",
"salary": "$137,500",
"start_date": "2018/08/06",
"office": "San Francisco",
"extn": "9608"
];
var myDataTable = $('#staff').DataTable(
sDom: 't',
data: myTableData,
columns: [
title: 'Name',
data: 'name'
,
title: 'Position',
data: 'position'
,
title: 'Office',
data: 'office'
,
title: 'Hire date',
data: 'start_date'
,
title: 'Salary',
data: 'salary'
]
);
// I instantiate the two datepickers here, instead of all at once like before.
// I also changed the dateFormat to match the format of the dates in the data table.
$("#startdate").datepicker(
"dateFormat": "yy/mm/dd",
"onSelect": function(date) // This handler kicks off the filtering.
minDateFilter = new Date(date).getTime();
myDataTable.draw(); // Redraw the table with the filtered data.
).keyup(function()
minDateFilter = new Date(this.value).getTime();
myDataTable.draw();
);
$("#enddate").datepicker(
"dateFormat": "yy/mm/dd",
"onSelect": function(date)
maxDateFilter = new Date(date).getTime();
myDataTable.draw();
).keyup(function()
maxDateFilter = new Date(this.value).getTime();
myDataTable.draw();
);
// The below code actually does the date filtering.
minDateFilter = "";
maxDateFilter = "";
$.fn.dataTableExt.afnFiltering.push(
function(oSettings, aData, iDataIndex)
if (typeof aData._date == 'undefined')
aData._date = new Date(aData[3]).getTime(); // Your date column is 3, hence aData[3].
if (minDateFilter && !isNaN(minDateFilter))
if (aData._date < minDateFilter)
return false;
if (maxDateFilter && !isNaN(maxDateFilter))
if (aData._date > maxDateFilter)
return false;
return true;
);
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
<label>Start date:</label>
<input id="startdate" class="date_range_filter" />
<label>End date:</label>
<input id="enddate" class="date_range_filter" />
<table id="staff"></table>
我还删除了“过滤器”按钮,因为在此实现中不需要它。当您从日期选择器中选择一个日期时,表格应该会自动更新。
【讨论】:
【参考方案2】:您的(稍作修改)示例具有一定的附加值(独立于时区、有限的年份范围、有界的日期选择器):
//Data definition
var myTableData =
[
"id": "1",
"name": "Tiger Nixon",
"position": "System Architect",
"salary": "$320,800",
"start_date": "2011/04/25",
"office": "Edinburgh",
"extn": "5421"
,
"id": "2",
"name": "Garrett Winters",
"position": "Accountant",
"salary": "$170,750",
"start_date": "2011/07/25",
"office": "Tokyo",
"extn": "8422"
,
"id": "3",
"name": "Ashton Cox",
"position": "Junior Technical Author",
"salary": "$86,000",
"start_date": "2009/01/12",
"office": "San Francisco",
"extn": "1562"
,
"id": "4",
"name": "Cedric Kelly",
"position": "Senior Javascript Developer",
"salary": "$433,060",
"start_date": "2012/03/29",
"office": "Edinburgh",
"extn": "6224"
,
"id": "5",
"name": "Airi Satou",
"position": "Accountant",
"salary": "$162,700",
"start_date": "2008/11/28",
"office": "Tokyo",
"extn": "5407"
,
"id": "6",
"name": "Brielle Williamson",
"position": "Integration Specialist",
"salary": "$372,000",
"start_date": "2012/12/02",
"office": "New York",
"extn": "4804"
,
"id": "7",
"name": "Herrod Chandler",
"position": "Sales Assistant",
"salary": "$137,500",
"start_date": "2012/08/06",
"office": "San Francisco",
"extn": "9608"
];
//Global variable for future use
var datepickers = [
id: 'startdate',
coid: 'enddate',
value: null,
limiter: 'minDate'
,
id: 'enddate',
coid: 'startdate',
value: null,
limiter: 'maxDate'
];
//Translate 'yy/mm/dd' string to UTC date
const yymmddUTC = str => new Date(...str.split('/').map((value,index) => index == 1 ? value-- : value));
//DataTables object definition
var myDataTable = $('#staff').DataTable(
sDom: 't',
data: myTableData,
columns: [
title: 'Name',
data: 'name'
,
title: 'Position',
data: 'position'
,
title: 'Office',
data: 'office'
,
title: 'Hire date',
data: 'start_date'
,
title: 'Salary',
data: 'salary'
]
);
//Limit datepicker options to those valid for current dataset
var dates = myDataTable.column(3).data().unique().sort();
var minDate = dates[0];
var maxDate = dates[dates.length-1];
//datepicker objects definition
$('.datepicker').datepicker(
dateFormat: 'yy/mm/dd',
changeMonth: true,
defaultDate: minDate,
changeYear: true,
yearRange: minDate.substr(0,4)+':'+maxDate.substr(0,4),
onSelect: function (selectedDate)
let datepicker = datepickers.find(entry => entry.id == $(this).attr('id'));
$(`#$datepicker.coid`).datepicker('option', datepicker.limiter, selectedDate);
datepicker.value = yymmddUTC(selectedDate);
myDataTable.draw();
).on('change', function()
datepickers[datepickers.findIndex(item => item.id == $(this).attr('id'))].value = yymmddUTC($(this).val());
myDataTable.draw();
);
//External search function
$.fn.DataTable.ext.search.push((settings, row) =>
let rowDate = yymmddUTC(row[3]);
return (rowDate >= datepickers[0].value || datepickers[0].value == null) && (rowDate <= datepickers[1].value || datepickers[1].value == null);
);
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css">
<link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script type="application/javascript" src="https://code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="application/javascript" src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script type="application/javascript" src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
</head>
<body>
<label>Start date:</label>
<input id="startdate" class="datepicker"></input>
<label>End date:</label>
<input id="enddate" class="datepicker"></input>
<table id="staff"></table>
</body>
</html>
【讨论】:
如果日期在数据表中为yyyy-mm-dd h:i:s
格式,我需要仅使用yyyy-mm-dd
进行搜索,而在数据表中显示格式为yyyy-mm-dd h:i:s
时如何执行此操作?任何建议都会有很大帮助。提前致谢。 @Curr195
我省略了 yymmddUTC 函数的使用,并使用@androidNoobie 的方法来获取时间格式与getTime()
代替您的日期过滤,因为我的日期时间为yy-mm-dd h:i:s
格式我遇到了一些困难无论如何,一开始@Cur195 和@AndroidNoobie 的回答都有助于完成工作。非常感谢
有一件事,在 chrome 中,日期选择器的输入字段显示以前选择的日期,如下拉列表,这很烦人,有什么提示可以解决这个问题吗?另外,我如何在过滤一次后取消选择日期并返回上一个完整列表? (对不起,如果这很烦人,但如果这与这个答案无关,会发布一个不同的问题。)【参考方案3】:
您必须添加此代码部分以获取日期范围和雇用日期。
$(document).ready(function()
$.fn.dataTable.ext.search.push(
function (settings, data, dataIndex)
var min = $('#startdate').datepicker("getDate");
var max = $('#enddate').datepicker("getDate");
var hireDate = new Date(data[3]);
if (min == null && max == null) return true;
if (min == null && hireDate <= max) return true;
if(max == null && hireDate >= min) return true;
if (hireDate <= max && hireDate >= min) return true;
return false;
);
);
而且你必须为你的按钮点击事件。
$("#filter").click(function ()
var myDataTable = $('#staff').DataTable();
myDataTable.draw();
);
第一部分获取日期,第二部分再次绘制数据表。
【讨论】:
以上是关于DataTables+Datepicker 按日期范围过滤表格的主要内容,如果未能解决你的问题,请参考以下文章
来自 Ajax 源的 DataTables 按数据顺序排序并显示格式化日期
angular-ui datepicker datepicker 的初始状态不是按 datepicker-popup 格式化的