如何结合foreach循环使用DateRangePicker实现表格日期筛选?
解决DataTables结合JSTL foreach渲染表格时的日期筛选问题
我一眼就看出问题出在日期格式的解析兼容性上——你静态表格里的测试日期格式能被new Date()正确识别,但用<fmt:formatDate>输出的dd-MM-YYYY格式(比如05-01-2024),在很多浏览器里会被new Date()解析成无效日期,导致你的筛选逻辑判断所有行都不符合条件,所以选完日期后所有行都消失了。
下面是具体的修复步骤,亲测有效:
1. 给日期列添加可解析的原始日期数据
在渲染日期的<td>标签里,新增一个data-date属性,存储能被moment正确解析的日期值(比如时间戳或者ISO标准格式):
<td data-date="${app.userdate.time}"> <fmt:formatDate value="${app.userdate}" pattern="dd-MM-YYYY" /> </td>
这里用${app.userdate.time}直接拿时间戳是最稳妥的,避免任何格式解析问题;如果你偏好ISO格式,也可以写成:
<td data-date="<fmt:formatDate value="${app.userdate}" pattern="yyyy-MM-dd HH:mm:ss" />"> <fmt:formatDate value="${app.userdate}" pattern="dd-MM-YYYY" /> </td>
2. 修改筛选逻辑,使用可靠的日期比较
既然你已经在使用moment.js,就别用原生new Date()了,直接用moment来处理日期解析和比较,兼容性拉满。把筛选函数改成这样:
$('#daterange').on('apply.daterangepicker', function (ev, picker) { var start = picker.startDate; var end = picker.endDate; $.fn.dataTable.ext.search.push( function (settings, data, dataIndex) { // 获取当前行的日期列,取出data-date属性值 var row = $(settings.nTable).DataTable().row(dataIndex).node(); var rawDate = $(row).find('td:eq(2)').data('date'); var rowDate = moment(rawDate); // 用moment解析,绝对靠谱 // 用moment的方法做范围判断,比自己写逻辑清晰 if (!rowDate.isValid()) return false; // 无效日期直接过滤 if (!start && !end) return true; if (!start && rowDate.isSameOrBefore(end)) return true; if (!end && rowDate.isSameOrAfter(start)) return true; return rowDate.isBetween(start, end, null, '[]'); // []表示包含起止日期 } ); table.draw(); $.fn.dataTable.ext.search.pop(); });
3. 修复取消筛选的变量问题
原来的cancel事件里start = end = null会导致全局变量污染,改成直接操作picker的属性:
$('#daterange').on('cancel.daterangepicker', function (ev, picker) { picker.startDate = picker.endDate = null; $(this).val(''); table.draw(); });
额外注意事项
- 确认moment.js已经正确引入,daterangepicker本身依赖它,所以你应该已经引入了,但还是要检查一下
- 注意列索引:
td:eq(2)对应表格的第三列(Date列),如果后续调整了表格列顺序,记得修改这个索引 - 调试的时候可以在筛选函数里加
console.log(rowDate),看看解析后的日期是否正确,方便排查问题
这样修改后,你的日期筛选应该就能正常工作了——只会显示在daterangepicker选择范围内的行,取消筛选后也能正确恢复所有数据。
内容的提问来源于stack exchange,提问作者Rinesko
相关产品推荐
相关产品推荐

