【发布时间】:2020-10-08 07:07:11
【问题描述】:
有没有办法在 Tabulator 表的列标题中实现日期范围过滤器?
【问题讨论】:
有没有办法在 Tabulator 表的列标题中实现日期范围过滤器?
【问题讨论】:
Header Filter Example Docs 包含一个针对整数的最大最小标头过滤器示例。
基于此,我们可以考虑为日期范围制作自己的自定义标题过滤器,在此示例中,我将使用内置的 Date 对象,但您可以选择任何适合您的日期库。我们还将假设日期将以 YYYY-MM-DD 格式输入,您可以使用您想要的任何日期选择器库来代替
首先我们将创建自定义过滤器编辑器(这将构建标题过滤器元素)
//custom max min header filter
var minMaxFilterEditor = function(cell, onRendered, success, cancel, editorParams){
var end;
var container = document.createElement("span");
//create and style inputs
var start = document.createElement("input");
start.setAttribute("type", "date");
start.setAttribute("placeholder", "Min");
start.style.padding = "4px";
start.style.width = "50%";
start.style.boxSizing = "border-box";
start.value = cell.getValue();
function buildValues(){
success({
start:start.value,
end:end.value,
});
}
function keypress(e){
if(e.keyCode == 13){
buildValues();
}
if(e.keyCode == 27){
cancel();
}
}
end = start.cloneNode();
end.setAttribute("placeholder", "Max");
start.addEventListener("change", buildValues);
start.addEventListener("blur", buildValues);
start.addEventListener("keydown", keypress);
end.addEventListener("change", buildValues);
end.addEventListener("blur", buildValues);
end.addEventListener("keydown", keypress);
container.appendChild(start);
container.appendChild(end);
return container;
}
然后我们将创建过滤器函数,按这些日期范围进行过滤:
//custom max min filter function
function minMaxFilterFunction(headerValue, rowValue, rowData, filterParams){
//headerValue - the value of the header filter element
//rowValue - the value of the column in this row
//rowData - the data for the row being filtered
//filterParams - params object passed to the headerFilterFuncParams property
//convert strings into dates
if(headerValue.start != ""){
headerValue.start = new Date(headerValue.start);
}
if(headerValue.end != ""){
headerValue.end = new Date(headerValue.end );
}
//compare dates
if(rowValue){
rowValue = new Date(rowValue);
if(headerValue.start != ""){
if(headerValue.end != ""){
return moment(rowValue) >= headerValue.start && rowValue <= headerValue.end;
}else{
return rowValue >= headerValue.start;
}
}else{
if(headerValue.end != ""){
return rowValue <= headerValue.end;
}
}
}
return true; //must return a boolean, true if it passes the filter.
}
然后我们可以使用 headerFilter 和 headerFilterFunc 属性将这些分配给列定义对象中的列:
{title:"Date of Birth", field:"dob", width:150, headerFilter:minMaxFilterEditor, headerFilterFunc:minMaxFilterFunction, headerFilterLiveFilter:false},
【讨论】:
return moment(rowValue) >= headerValue.start && rowValue <= headerValue.end; 应该是 return rowValue >= headerValue.start && rowValue <= headerValue.end; 这个时间戳比较不需要 Moment 库。
<!DOCTYPE html>
<html>
<head>
<title>Table</title>
<link href="https://unpkg.com/tabulator-tables@4.6.2/dist/css/tabulator.min.css" rel="stylesheet">
<link href="dist/css/bootstrap/tabulator_bootstrap.min.css" rel="stylesheet">
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.6.3/css/font-awesome.min.css'>
<link rel='stylesheet' href='https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.css'>
<link rel='stylesheet' href='https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css'>
<script type="text/javascript" src="https://unpkg.com/tabulator-tables@4.6.2/dist/js/tabulator.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js'></script>
<script src='https://cdn.jsdelivr.net/npm/daterangepicker/daterangepicker.min.js'></script>
<link href='https://fonts.googleapis.com/css?family=Lato' rel='stylesheet'>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="keywords" content="" />
</head>
<style>
body {
font-family: 'Lato';font-size: 22px;
}
.tabulator-row.tabulator-row-even {
background-color: #fbfcfd;
}
.tabulator-row .tabulator-cell {
border-right: 1px solid #e7ecf1;
}
.tabulator .tabulator-header .tabulator-col {
border-right: 1px solid #d4d4d4;
}
</style>
<body>
<!--<table id="example-table">
<thead>
<tr>
<th width="200">11111</th>
<th tabulator-align="center">2222</th>
<th>3333</th>
<th>4444</th>
<th width="150">555555</th>
<th>6</th>
</tr>
</thead>
<tbody>
<tr>
<td>Billy Bob</td>
<td>12</td>
<td>male</td>
<td>1</td>
<td>red</td>
<td>22/04/1994</td>
</tr>
<tr>
<td>Mary May</td>
<td>1</td>
<td>female</td>
<td>2</td>
<td>blue</td>
<td>14/05/1982</td>
</tr>
</tbody>
</table>-->
<div style="padding:0px 0px 20px 0px">
<button id="reactivity-add">Add New Row</button>
<button id="reactivity-delete">Remove Row</button>
<button id="reactivity-update">Update First Row Name</button>
<button id="hidecar" onclick="hidecol('car')">Hide Driver Col</button>
<button id="showcar" onclick="showcol('car')">Show Driver Col</button>
</div>
<div id="example-table"></div>
<script>
//**********define row context menu starts*****************
var headerMenu = [
{
label:"Hide Column",
action:function(e, column){
column.hide();
}
},
]
//**********define row context menu ends*****************
//************Create Date Editor starts*****************
var dateEditor = function(cell, onRendered, success, cancel){
//cell - the cell component for the editable cell
//onRendered - function to call when the editor has been rendered
//success - function to call to pass the successfuly updated value to Tabulator
//cancel - function to call to abort the edit and return to a normal cell
//create and style input
var cellValue = moment(cell.getValue(), "DD/MM/YYYY").format("YYYY-MM-DD"),
input = document.createElement("input");
input.setAttribute("type", "date");
input.style.padding = "4px";
input.style.width = "100%";
input.style.boxSizing = "border-box";
input.value = cellValue;
onRendered(function(){
input.focus();
input.style.height = "100%";
});
function onChange(){
if(input.value != cellValue){
success(moment(input.value, "YYYY-MM-DD").format("DD/MM/YYYY"));
}else{
cancel();
}
}
//submit new value on blur or change
input.addEventListener("blur", onChange);
//submit new value on enter
input.addEventListener("keydown", function(e){
if(e.keyCode == 13){
onChange();
}
if(e.keyCode == 27){
cancel();
}
});
return input;
};
//************Create Date Editor ends*****************
var table = new Tabulator("#example-table", {
layout:"fitColumns", //fit columns to width of table (optional)
responsiveLayout:"hide",//Responsive
//selectable:true,//highlight row on select
height:"auto",
//maxHeight:"100%",
height:"335px",
tooltips:true,
fitColumns:true,
rowContextMenu: "rowMenu", //add context menu to rows
addRowPos:"top",
scrollToRowPosition :"top",
footerElement:"<button>Custom Button</button>",
movableRows: true, //Drag and Drop Rows
movableColumns: true, //Drag and Drop column
resizableRows:true, //allow row order to be changed
history:true, //allow undo and redo actions on the table
paginationSize:7, //allow 7 rows per page of data
virtualDomHoz:true,
reactiveData:true, //turn on data reactivity
data:"tabledata", //load data into table
rowClick:function(e, row){ //trigger an alert message when the row is clicked
//alert("Row " + row.getData().id + " Clicked!!!!");
},
//tooltip
tooltips:function(cell){
//cell - cell component
//function should return a string for the tooltip of false to hide the tooltip
return cell.getColumn().getField() + " - " + cell.getValue(); //return cells "field - value";
},
//Filters
headerFilterPlaceholder:"filter data...", //set column header placeholder text
columns:[
{title:"", field:"", cssClass: "text-underline", headerSort:false, headerFilter:true, headerFilter:"input", formatter:"rowSelection", frozen:true, titleFormatter:"rowSelection", width:50, hozAlign:"center", cellClick:function(e, cell){cell.getRow().toggleSelect();}},
{title:"Name", field:"name", headerFilter:true, headerFilterPlaceholder:"Search Name..", headerFilter:"select",responsive:0,editor:"input", validator:["minLength:3", "maxLength:10", "string"],headerMenu:headerMenu},
{title:"Progress", headerMenu:"headerMenu",headerFilter:"select", field:"progress", width:150, formatter:"progress", sorter:"number", headerFilterPlaceholder:"Filter by (%)..",headerMenu:headerMenu},
{title:"Gender", headerMenu:"headerMenu", field:"gender", responsive:0, editor:"select", editorParams:{"male":"Male", "female":"Female"}, headerFilter:true, headerFilterPlaceholder:"Select Gender", headerFilterParams:{"male":"Male", "female":"Female"},headerMenu:headerMenu},
{title:"Rating", headerMenu:"headerMenu", field:"rating", editor:"star", align:"center", responsive:0,headerFilter:"number", headerFilterPlaceholder:"at least...", headerFilterFunc:">=",headerMenu:headerMenu},
{title:"Favourite Color", headerMenu:"headerMenu",field:"col", headerFilter:"input",responsive:0,headerMenu:headerMenu},
{title:"Date of Birth", field:"dob", width:150, headerFilter:minMaxFilterEditor, headerFilterFunc:minMaxFilterFunction, headerFilterLiveFilter:false},
{title:"Driver", field:"car", hozAlign:"center", formatter:"tickCross", headerFilter:"tickCross", headerFilterParams:{"tristate":true},headerFilterEmptyCheck:function(value){return value == null},headerMenu:headerMenu},
{title:"", field:"", width:50, headerMenu:headerMenu, headerSort:false,allowEmpty:true, allowTruthy:true, tickElement:"<i class='fa fa-check'></i>", crossElement:"<i class='fa fa-times'></i>"},
],
initialSort:[ //set the initial sort order of the data
{column:"name", dir:"asc"},
],
//freeze first row on data load
/*dataLoaded:function(data){
var firstRow = this.getRows()[0];
if(firstRow){
firstRow.freeze();
}
},*/
//pagination
pagination:"local", //enable local pagination.
paginationAddRow:"table",
paginationSizeSelector:[7, 10, 15, 20, 25],
movableColumns:true,
});
//add row to bottom of table on button click
document.getElementById("reactivity-add").addEventListener("click", function(){
tabledata.push({name:"IM A NEW ROW", progress:100, gender:"male"});
});
//remove bottom row from table on button click
document.getElementById("reactivity-delete").addEventListener("click", function(){
tabledata.pop();
});
//update name on first row in table on button click
document.getElementById("reactivity-update").addEventListener("click", function(){
tabledata[0].name = "IVE BEEN UPDATED";
});
//*****Show hide columns with buttons starts*********************
const columns = table.getColumns(true);
hidecol = (colName) => {
columns.forEach((col) => {
if (col.getDefinition().field === colName) {
col.hide();
}
});
}
showcol = (colName) => {
columns.forEach((col) => {
if (col.getDefinition().field === colName) {
col.show();
}
});
}
//*****Show hide columns with buttons ends*****************
//****************************Create Date Editor Starts*************************
var dateEditor = function(cell, onRendered, success, cancel){
//cell - the cell component for the editable cell
//onRendered - function to call when the editor has been rendered
//success - function to call to pass the successfuly updated value to Tabulator
//cancel - function to call to abort the edit and return to a normal cell
//create and style input
var cellValue = moment(cell.getValue(), "DD/MM/YYYY").format("YYYY-MM-DD"),
input = document.createElement("input");
input.setAttribute("type", "date");
input.style.padding = "4px";
input.style.width = "100%";
input.style.boxSizing = "border-box";
input.value = cellValue;
onRendered(function(){
input.focus();
input.style.height = "100%";
});
function onChange(){
if(input.value != cellValue){
success(moment(input.value, "YYYY-MM-DD").format("DD/MM/YYYY"));
}else{
cancel();
}
}
//submit new value on blur or change
input.addEventListener("blur", onChange);
//submit new value on enter
input.addEventListener("keydown", function(e){
if(e.keyCode == 13){
onChange();
}
if(e.keyCode == 27){
cancel();
}
});
return input;
};
//****************************Create Date Editor Ends*************************
//custom max min header filter
var minMaxFilterEditor = function(cell, onRendered, success, cancel, editorParams){
var end;
var container = document.createElement("span");
//create and style inputs
var start = document.createElement("input");
start.setAttribute("type", "date");
start.setAttribute("placeholder", "Min");
start.style.padding = "4px";
start.style.width = "50%";
start.style.boxSizing = "border-box";
start.value = cell.getValue();
function buildValues(){
success({
start:start.value,
end:end.value,
});
}
function keypress(e){
if(e.keyCode == 13){
buildValues();
}
if(e.keyCode == 27){
cancel();
}
}
end = start.cloneNode();
end.setAttribute("placeholder", "Max");
start.addEventListener("change", buildValues);
start.addEventListener("blur", buildValues);
start.addEventListener("keydown", keypress);
end.addEventListener("change", buildValues);
end.addEventListener("blur", buildValues);
end.addEventListener("keydown", keypress);
container.appendChild(start);
container.appendChild(end);
return container;
}
//custom max min filter function
function minMaxFilterFunction(headerValue, rowValue, rowData, filterParams){
//headerValue - the value of the header filter element
//rowValue - the value of the column in this row
//rowData - the data for the row being filtered
//filterParams - params object passed to the headerFilterFuncParams property
//convert strings into dates
if(headerValue.start != ""){
headerValue.start = new Date(headerValue.start);
}
if(headerValue.end != ""){
headerValue.end = new Date(headerValue.end );
}
//compare dates
if(rowValue){
rowValue = new Date(rowValue);
if(headerValue.start != ""){
if(headerValue.end != ""){
return moment(rowValue) >= headerValue.start && rowValue <= headerValue.end;
}else{
return rowValue >= headerValue.start;
}
}else{
if(headerValue.end != ""){
return rowValue <= headerValue.end;
}
}
}
return true; //must return a boolean, true if it passes the filter.
}
//date ranges
$(function() {
var table = $("#example").DataTable();
// Date range vars
minDateFilter = "";
maxDateFilter = "";
$("#daterange").daterangepicker();
$("#daterange").on("apply.daterangepicker", function(ev, picker) {
minDateFilter = Date.parse(picker.startDate);
maxDateFilter = Date.parse(picker.endDate);
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
var date = Date.parse(data[1]);
if (
(isNaN(minDateFilter) && isNaN(maxDateFilter)) ||
(isNaN(minDateFilter) && date <= maxDateFilter) ||
(minDateFilter <= date && isNaN(maxDateFilter)) ||
(minDateFilter <= date && date <= maxDateFilter)
) {
return true;
}
return false;
});
table.draw();
});
});
//**************************define row context menu contents Ending)**********************
var tabledata = [
{id:1, name:"Andy", progress:100, gender:"male", rating:1, col:"red",height:1, dob:"8/10/2020", car:1, lucky_no:5},
{id:2, name:"Mary May", progress:70, gender:"female", rating:2, col:"blue", dob:"9/10/20220", car:2, lucky_no:10},
{id:3, name:"Chris", progress:50, gender:"male", rating:1, col:"red", dob:"14/04/1984", car:2, lucky_no:5},
{id:4, name:"Sourav", progress:10, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10},
{id:5, name:"Dev", progress:30, gender:"male", rating:1, col:"red", dob:"14/04/1984", car:2, lucky_no:5},
{id:6, name:"May", progress:1, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10},
{id:7, name:"Joker", progress:8, gender:"male", rating:1, col:"red", dob:"14/04/1984", car:2, lucky_no:5},
{id:8, name:"Balcky", progress:1, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10},
{id:9, name:"Browny", progress:18, gender:"male", rating:1, col:"red", dob:"14/04/1984", car:2, lucky_no:5},
{id:10, name:"Shaun", progress:90, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10},
{id:11, name:"Ram", progress:100, gender:"male", rating:1, col:"red", dob:"14/04/1984", car:1, lucky_no:5},
{id:12, name:"Krish", progress:71, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10},
{id:13, name:"Ravan", progress:18, gender:"male", rating:1, col:"red", dob:"14/04/1984", car:1, lucky_no:5},
{id:14, name:"Karnan", progress:81, gender:"female", rating:2, col:"blue", dob:"14/05/1982", car:true, lucky_no:10},
{id:15, name:"Dhur", progress:62, gender:"male", rating:1, col:"red", dob:"14/04/1984", car:1, lucky_no:5},
];
//load sample data into the table
table.setData(tabledata);
</script>
</body>
</html>
【讨论】: