为啥在单击“全选”按钮后,复选框会被选中,然后又被取消选中?
Posted
技术标签:
【中文标题】为啥在单击“全选”按钮后,复选框会被选中,然后又被取消选中?【英文标题】:Why do boxes become checked and then unchecked after clicking a “Check All” button?为什么在单击“全选”按钮后,复选框会被选中,然后又被取消选中? 【发布时间】:2021-08-16 05:55:19 【问题描述】:我在这里尝试修复一个 JS 函数。单击“检查全部”按钮时会触发此功能。单击此按钮时,应选中并禁用表中的所有项目。当我运行此功能并单击 Check All 按钮时,所有项目都被短暂选中,然后它们又回到未选中状态。我做错了什么?
PS:我尝试添加 e.preventDefault() 和末尾 功能和它不起作用
$(document).ready(function ()
$('body').on('change', '#checkAll', function (e)
if(this.checked)
let boxes = $("input.promo-action-checkbox");
boxes.toArray().forEach(element =>
console.log(element);
$(element).attr('disabled', 'disabled');
var name = $(element).data('name');
var number = $(element).data('number');
var user = $(element).data('user');
$.ajax(
method: 'post',
url: '/checker',
contentType: "application/json",
data: JSON.stringify(
name: name,
number: number,
user: user
),
dataType: 'json',
error: function ()
$(element).attr('disabled', '');
)
);
html表格中的列是如何组成的:
var table = $('#datatable').DataTable(
pageLength: 20,
lengthChange: false,
language:
paginate:
previous: '<i class=\'fas fa-angle-left\'>',
next: '<i class=\'fas fa-angle-right\'>'
,
ordering: true,
processing: true,
serverSide: true,
ajax:
url: '/table/',
dataSrc: 'results'
,
columns: [
data: null,
render: function (data, type, row, meta)
let rowHtml = '<div class="custom-control custom-checkbox mb-3"> <input class="custom-control-input promo-action-checkbox" id="checkbox-' + meta.row + '" data-name="' + row.name + '" data-phone="' + row.number + '" data-admin="' + row.user + '" type="checkbox"'
if (row.fulfilled)
rowHtml += ' disabled checked'
rowHtml += '> <label class="custom-control-label" for="checkbox-' + meta.row + '"></label></div>'
return rowHtml
,
searchable: true,
data: 'name'
]
);
这是可行的,但是“checkAll”框没有被勾选。此表也不在表单内。
$('#checkAll').click(function (e)
e.preventDefault()
$('input.action-checkbox').prop('checked', this.checked);
$('input.action-checkbox').prop('disabled', true);
return false;
)
表结构:
<div class="table-responsive">
<table class="table align-items-center table-flush table-striped" id="datatable-promo-code">
<thead class="thead-light">
<tr>
<th>Check All <input id = "checkAll" type= "checkbox"></th>
<th>Name</th>
<th>Info</th>
<th>address</th>
<th>Email</th>
<th>Number</th>
</tr>
</thead>
<tbody>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
</div>
【问题讨论】:
请添加所有相关代码(HTML、CSS 和 javascript),以便我们复制您的问题。 @ScottMarcus 我刚刚更新了它 您的 ajax 调用一定失败了,因为error
函数是重新启用它们的原因。您正在传递datatype: 'json'
,因此无需调用stringify
,jQuery 会为您执行此操作,只需直接传递 json 对象即可。至于他们为什么不勾选,不知道,没有相关的代码。
现在,我不介意他们被禁用。我只希望 ClickAll 按钮检查并禁用所有其他按钮并保持这种状态,直到我手动刷新页面
检查你的 if(this.checked) 语句被调用了多少次。我之所以这么说,是因为在将事件处理程序多次绑定到同一个对象之前,我在使用 JQuery On 方法时遇到了问题。
【参考方案1】:
很难说,因为我实际上无法运行您的代码...但我会将 console.log 放入渲染函数中,只是为了查看它何时被调用。我的猜测是,在您的 'change'
侦听器完成所有请求之前,您的表正在重新渲染。如果是这种情况,您需要等待所有承诺结束,然后再手动刷新页面或重新呈现表格......类似......
$(document).ready(function ()
$('body').on('change', '#checkAll', async function (e)
if(this.checked)
let boxes = $("input.promo-action-checkbox");
const promises = boxes.toArray().map(element =>
return new Promise(function (resolve, reject)
$(element).attr('disabled', 'disabled');
var name = $(element).data('name');
var number = $(element).data('number');
var user = $(element).data('user');
$.ajax(
method: 'post',
url: '/checker',
contentType: "application/json",
data: JSON.stringify(
name: name,
number: number,
user: user
),
dataType: 'json',
error: function ()
$(element).attr('disabled', '');
reject();
,
success: function()
resolve()
);
);
);
await Promise.all(promises);
// refresh the page
document.location.reload()
// or re-render your table... no ideia how to that though...
someMagicFunctionToReRenderYourTable()
);
);
【讨论】:
谢谢你!我得到一个 ReferenceError: promises is not defined。顺便说一下,我正在 中实现这个 你能把代码给我看看吗?您可能会收到此错误,但为此您可能已将Promise.all
放在 if
之外...
请检查我对这个问题的更新,我已经发布了有效的方法,但我遇到了显示已勾选复选框的问题。我还包括了表格的样子【参考方案2】:
目前尚不清楚为什么所有复选框不仅需要被选中而且还需要禁用。单击 "button" 后,其余代码在做什么也不是很清楚。更重要的是,这是<table>
在<form>
中吗?如果是这样,那么<form>
可能会自行重置(“提交”事件的默认行为)
抛开所有这些,我们可以将代码隔离成更小的部分。这样我们就可以在不破坏其他内容(即 AJAX POST 请求)的情况下修复某些内容(即像 <input>
这样的交互式元素)。
下面的例子将:
-
监听“change”事件以触发仅
#checkAll
一旦触发,事件处理程序lockCells()
将运行。
$('#checkAll').on('change', lockCells);
lockCells(event) ...
传递 Event Object
...
...检查#checkAll
(this
) 是否为.checked
。
let status = this.checked ? true : false;
...然后收集任何<table>
中的所有<input>
并在每个.prop()
上运行方法。
$('table input').prop(...)
...带有“已禁用”和“已检查”的参数,在第 4 步之前确定的真/假布尔值
'disabled': status,
'checked': status
重要的是要注意:虽然方法.attr()
用于操作属性,但.prop()
是属性的更好选择,尤其是具有布尔值(T/F)的属性。详情请参考question。
$('#checkAll').on('change', lockCells);
function lockCells(event)
let status = this.checked ? true : false;
$('table input').prop(
'disabled': status,
'checked': status
);
;
label
display: inline-block;
padding: 3px 5px;
border: 1px inset grey;
border-radius: 6px;
margin: 5px 10px;
float: right;
cursor: pointer;
label::before
content: 'Disable ';
#checkAll:checked+label::before
content: 'Enable ';
table input
display: block;
width: 10ch;
<input id='checkAll' type='checkbox' hidden>
<label for='checkAll'> All Cells</label>
<table>
<tbody>
<tr>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
</tr>
<tr>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
</tr>
<tr>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
</tr>
<tr>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
<td><input type='checkbox'></td>
</tr>
</tbody>
</table>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
【讨论】:
请检查我对这个问题的更新,我已经发布了有效的方法,但是原始复选框没有显示它已被选中,所以我几乎在那里。顺便说一下,我还包括了表格的外观。 您需要跟踪两种状态。您可以通过使用复选框以实用的方式或更简单的方式执行此操作。发布的新代码与我的回答非常相似。不同之处在于您的状态从一种状态开始并保持这种状态,而我的状态从一种状态切换到另一种状态(切换)。顺便说一句,将“已检查”值从 this.checked 更改为 true。在当前上下文中,这指向#checkAll 我对您的回答的问题是,在消失之前检查了盒装半秒,使用 e.preventDefault() 和返回 false,更改仍然存在,但我不知道为什么。此外,当我单击复选框时,该框不会被明显选中。也许这与我使用 .click(function (e)) 而不是 onchange 有关? 在您的布局中,复选框由 dataTable 插件动态生成,我假设每个输入都有 3 个 data-* 属性,这些属性的值由 AJAX 获得的 JSON 填充。看起来所有这些都是通过单击#checkall 来实现的。复选框最初是在页面加载时生成的吗?您需要为服务器中的复选框分配值吗? #checkAll 是隐藏的,与之相关的标签看起来像一个按钮。如果您希望看到它被选中,只需删除 hidden 属性。不要使用 e.preventDefault()。更改事件是专门用于输入的事件,其他表单控件不使用点击事件。使用我发布的内容,仅将选择器“表格输入”更改为“input.action-checkbox”。以上是关于为啥在单击“全选”按钮后,复选框会被选中,然后又被取消选中?的主要内容,如果未能解决你的问题,请参考以下文章