背景: 项目使用 vue.js + datatables + jquery
需求: 在每行的前面加上 checkbox 然后实现多选 反选
遇到的问题:
由于是服务端分页,查看下一页再返回上一页 之前的多选框的选中状态就不见了,看文档发现没有什么好的解决方法,官网给出的 demo 是没有全选反选的功能。只好自己下决心把这个功能实现!
写代码之前要考虑到几种场景:
1.切换页面 记住 checkbox 的选中状态
2.当前页面如果手动把所有的 checkbox 都选上了 那最上边的 checkbox 也要是选中的状态
3.一旦全选,取消任意一个 checkbox 的选中,那么 最上边的 checkbox 要取消选中
4.如果切换到当前的页面所有的 checkbox 都被选中了 那么 最上边的 checkbox 也要是选中的状态
5.点击全选,把未选中的 checkbox 选中
6.点击取消全选,肯定是因为上一步你的操作是全选上了,只需要把当页的数据从数组里移出去就好
ps:其实这六点注意,大多数都是对 全选按钮的状态控制
代码实现:
1> 记住 checkbox 的选中状态 回到该页 如果数据都被选中 全选框也为选中状态
selected 为存放选中值的数组
var table = $('#patients').on('xhr.dt', function ( e, settings, json, xhr ) {
var flag = true
let data = json.aData.map((d) => {return d.id})
self.currentData = data
for (let i = 0;i < data.length;i++) {
if (self.selected.indexOf(data[i]) === -1) {
flag = false
break
}
}
$(".checkall").prop("checked", flag)
} ).DataTable({
复制代码
"rowCallback": function( row, data ) {
if ( $.inArray(data.id, self.selected) !== -1 ) {
$(row).find('input[type=checkbox]').prop('checked', true)
}
},
"aoColumns" : [ {
"sClass": "text-center",
"data": "id",
"render": function (data, type, full, meta) {
return '<input type="checkbox" class="checkchild" value="' + data + '" />';
},
"bSortable": false
},
复制代码
$("#patients").on("click", 'td input[type=checkbox]', function () {
let checked = $(this).prop("checked")
if (checked === true) {
self.selected.push(this.value)
// 如果页面上的 checkbox 全选上了 将 checkall 赋值为 true
if ($(".checkchild:checked").length === self.currentData.length) {
$(".checkall").prop("checked", true)
}
} else {
// 一旦取消选中 则将全选按钮赋值为 false
$(".checkall").prop("checked", false)
let index = self.selected.indexOf(this.value)
self.selected.splice(index, 1)
}
console.log(self.selected);
});
复制代码
2> 点击全选 所有的 checkbox 为选中
这里我用到了两个方法:
1.将所有选中的从 selected 里去掉 然后再把当页数据添加到 selected 里
2.将所有未选中的 checkbox 的 value 添加到 selected 里
自我感觉 第二种方式会比较友好... (注释的代码是第一种方法)
ps:你之所有能点击取消全选,一定是你上一步把所有的 checkbox 都选中了,所以取消全选,只需要遍历当前页面数据从 selected 移出去即可
$(".checkall").click(function () {
var checked = $(this).prop("checked")
// 把当前页选中的从 selected 去掉 再全部 concat 进去
if (checked === true) {
$(".checkchild").not("input:checked").each(function () {
self.selected.push($(this)[0].value)
})
// self.currentData.map((data) => {
// self.selected.map((d) => {
// let index = self.selected.indexOf(data)
// if (index !== -1) {
// self.selected.splice(index, 1)
// }
// })
// })
// self.selected = self.selected.concat(self.currentData)
} else {
self.currentData.map((data) => {
let index = self.selected.indexOf(data)
self.selected.splice(index, 1)
})
}
$(".checkchild").prop("checked", checked)
console.log(self.selected);
});
复制代码
目前测试没问题,大家有任何疑问欢迎提出!