如何实现DataTables日期列的范围滑块筛选功能
日期范围筛选器实现方案
问题背景
现有基于ion range slider的范围筛选逻辑仅支持整数类型列(比如年龄),无法适配日期类型列的筛选需求,可接受不局限于该插件的可行实现方案。示例中日期为模拟数据,实际场景将使用数据集返回的标准格式真实日期。
原有可运行的整数筛选代码
HTML部分
<!DOCTYPE html> <html> <head> <!-- 插件样式文件 --> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/css/ion.rangeSlider.min.css" /> <!-- jQuery依赖 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <!-- 滑块插件脚本 --> <script src="https://cdnjs.cloudflare.com/ajax/libs/ion-rangeslider/2.3.1/js/ion.rangeSlider.min.js"></script> <link href="https://nightly.datatables.net/css/jquery.dataTables.css" rel="stylesheet" type="text/css" /> <script src="https://nightly.datatables.net/js/jquery.dataTables.js"></script> <meta charset=utf-8 /> <title>DataTables - 日期范围筛选</title> </head> <body> <div class="container"> <table border="0" cellspacing="5" cellpadding="5"> <thead> <tr> <th colspan="3"> <h4>入职日期筛选</h4> </th> </tr> </thead> <tbody> <tr> <td> <p class="js-input-from" id="min" name="min" value="0" /> </td> <td style="width:300px;"><input type="text" class="js-range-slider" value="" /></td> <td> <p class="js-input-to" id="max" name="max" value="0" /> </td> </tr> </tbody> </table> <table id="example" class="display" style="width:100%"> <thead> <tr> <th>姓名</th> <th>职位</th> <th>办公地点</th> <th>年龄</th> <th>入职日期</th> <th>薪资</th> </tr> </thead> <tbody> <tr> <td>Tiger Nixon</td> <td>系统架构师</td> <td>爱丁堡</td> <td>61</td> <td>2011/04/25</td> <td>$320,800</td> </tr> <tr> <td>Garrett Winters</td> <td>会计</td> <td>东京</td> <td>63</td> <td>2011/07/25</td> <td>$170,750</td> </tr> <tr> <td>Ashton Cox</td> <td>初级技术专员</td> <td>旧金山</td> <td>66</td> <td>2009/01/12</td> <td>$86,000</td> </tr> <tr> <td>Cedric Kelly</td> <td>高级Javascript开发</td> <td>爱丁堡</td> <td>22</td> <td>2012/03/29</td> <td>$433,060</td> </tr> <tr> <td>Airi Satou</td> <td>会计</td> <td>东京</td> <td>33</td> <td>2008/11/28</td> <td>$162,700</td> </tr> <tr> <td>Brielle Williamson</td> <td>集成专员</td> <td>纽约</td> <td>61</td> <td>2012/12/02</td> <td>$372,000</td> </tr> </tbody> </table> </div> </body> </html>
原有整数筛选逻辑JS
$.fn.dataTable.ext.search.push( function (settings, data, dataIndex) { var min = parseInt($('#min').val(), 10); var max = parseInt($('#max').val(), 10); var age = parseFloat(data[3]) || 0; // 读取年龄列数据 if ((isNaN(min) && isNaN(max)) || (isNaN(min) && age <= max) || (min <= age && isNaN(max)) || (min <= age && age <= max)) { return true; } return false; } ); $(document).ready(function () { var table = $('#example').DataTable(); // 输入框值变化时重绘表格触发筛选 $('#min, #max').keyup(function () { table.draw(); }); }); // Ion Range Slider 初始化 var $range = $(".js-range-slider"), $inputFrom = $(".js-input-from"), $inputTo = $(".js-input-to"), instance, min = 10, max = 70, from = 0, to = 0; $range.ionRangeSlider({ type: "double", min: min, max: max, onStart: updateInputs, onChange: updateInputs, onFinish: updateInputs }); instance = $range.data("ionRangeSlider"); function updateInputs(data) { from = data.from; to = data.to; $inputFrom.prop("value", from); $inputTo.prop("value", to); // 触发重绘 $('#min').trigger('keyup'); } $inputFrom.on("input", function () { var val = $(this).prop("value"); // 边界校验 if (val < min) { val = min; } else if (val > to) { val = to; } instance.update({ from: val }); }); $inputTo.on("input", function () { var val = $(this).prop("value"); // 边界校验 if (val < from) { val = from; } else if (val > max) { val = max; } instance.update({ to: val }); });
日期筛选适配修改
核心思路:不需要更换插件,把所有日期统一转换为时间戳(整数类型),完全复用现有数值比较逻辑即可,改动量极小
- 初始化DataTable后,遍历入职日期列(第5列,索引4),提取所有日期转时间戳,算出最小、最大值作为滑块的取值范围
- 配置ion range slider的格式化回调,滑块内部传时间戳计算,对外展示时转成
YYYY/MM/DD可读格式 - 修改筛选函数,把当前行的入职日期转成时间戳,和滑块选中的起止时间戳做大小比较
修改后的完整JS代码
// 日期格式化工具:时间戳转 YYYY/MM/DD function formatDate(timestamp) { const d = new Date(timestamp); const year = d.getFullYear(); const month = String(d.getMonth() + 1).padStart(2, '0'); const day = String(d.getDate()).padStart(2, '0'); return `${year}/${month}/${day}`; } $.fn.dataTable.ext.search.push( function (settings, data, dataIndex) { const min = parseInt($('#min').val(), 10); const max = parseInt($('#max').val(), 10); // 读取入职日期列,转时间戳 const rowDate = new Date(data[4]).getTime() || 0; return (isNaN(min) && isNaN(max)) || (isNaN(min) && rowDate <= max) || (min <= rowDate && isNaN(max)) || (min <= rowDate && rowDate <= max); } ); $(document).ready(function () { const table = $('#example').DataTable(); // 提取日期列的最小、最大时间戳 const dateData = table.column(4).data().map(dateStr => new Date(dateStr).getTime()); const minDate = Math.min(...dateData); const maxDate = Math.max(...dateData); // 初始化滑块 const $range = $(".js-range-slider"), $inputFrom = $(".js-input-from"), $inputTo = $(".js-input-to"); let instance, from = minDate, to = maxDate; $range.ionRangeSlider({ type: "double", min: minDate, max: maxDate, from: minDate, to: maxDate, // 自定义滑块提示和输入框展示格式 prettify: function (num) { return formatDate(num); }, onStart: updateInputs, onChange: updateInputs, onFinish: updateInputs }); instance = $range.data("ionRangeSlider"); function updateInputs(data) { from = data.from; to = data.to; // 输入框存时间戳,展示格式化后的日期 $inputFrom.prop("value", from).text(formatDate(from)); $inputTo.prop("value", to).text(formatDate(to)); table.draw(); } // 手动输入日期的校验逻辑,不需要可以删除 $inputFrom.on("input", function () { let val = new Date($(this).text()).getTime(); if (isNaN(val) || val < minDate) val = minDate; if (val > to) val = to; instance.update({ from: val }); }); $inputTo.on("input", function () { let val = new Date($(this).text()).getTime(); if (isNaN(val) || val > maxDate) val = maxDate; if (val < from) val = from; instance.update({ to: val }); }); });
补充说明
- 只要传入的日期是标准可解析格式(比如
YYYY/MM/DD、YYYY-MM-DD、ISO时间字符串),new Date()都可以正确转成时间戳,不需要额外做格式处理 - 滑块展示的日期格式可以根据需求自行修改
formatDate函数调整 - 如果后续需要支持时间精度到时分秒,只需要保留时间戳的完整值,修改格式化函数即可,核心筛选逻辑不用动
内容的提问来源于stack exchange,提问作者kodikai
相关产品推荐
相关产品推荐

