[英]Can't check radio button programmatically with preventDefault()
I have some elements (for example divs with class .label) with radio buttons inside of each. 我有一些元素(例如带有类.label的div),每个元素都有单选按钮。 When user clicks this "labels" I programmatically set radio in it as selected.
当用户单击此“标签”时,我以编程方式将其中的无线电设置为已选中。 But if I use preventDefault() for click event, the radio didn't selected if user clicked exactly on radio.
但是如果我使用preventDefault()进行点击事件,如果用户完全点击无线电,则无法选择收音机。
Please help me to understand this strange behaviour. 请帮我理解这种奇怪的行为。 I know the solution, I know why preventDefault() on parent element disallows to check radio, but I want to understand, why click event on radio can disallow to set its state programmatically .
我知道解决方案,我知道为什么在父元素上的preventDefault()不允许检查无线电,但我想明白,为什么无线电上的click事件可以禁止以编程方式设置其状态 。 You will see that click on radio button will say that radio is checked, but it's not.
你会看到单击单选按钮会说收音机已被选中,但事实并非如此。
$(function () { $('.label').on('click', function(e) { var $radio = $(this).find(':radio') console.log('before prevent', `checked=${$radio.prop('checked')}`, `prevented=${e.isDefaultPrevented()}`); e.preventDefault(); if (!$(this).hasClass('checked')) { $('.checked').removeClass('checked'); $(this).addClass('checked'); } $radio.prop('checked', true); console.log('after prevent', `checked=${$radio.prop('checked')}`, `prevented=${e.isDefaultPrevented()}`); setTimeout(function () { console.log('after timeout', `checked=${$radio.prop('checked')}`); }, 500); }); $(':radio').on('click', function (e) { console.log('click', `prevented=${e.isDefaultPrevented()}`); }); });
.label { padding: 10px; margin-bottom: 10px; border: 1px solid #000; } .label.checked { background-color: green; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div class="label"> Label 1 <input type="radio" name="radio" value="1"> </div> <div class="label"> Label 2 <input type="radio" name="radio" value="2"> </div>
UPDATE . 更新 。 How do I see this situation:
我怎么看这种情况:
.label
.label
上触发 cancelled
flag. cancelled
标志。 div
getting class '.checked' and radio setted as checked again, now programmatically. div
将类'.checked'和radio设置为再次检查,现在以编程方式。 Am I right? 我对吗?
How do I see this situation (inspired by https://stackoverflow.com/a/15767580/11357125 ): 我如何看待这种情况(受https://stackoverflow.com/a/15767580/11357125启发):
<input>
<input>
<div>
, it is handled. <div>
,它被处理。 Event listener calls the preventDefault
method, setting an internal cancelled
flag. preventDefault
方法,设置内部cancelled
标志。 <div>
getting class '.checked' and radio setted as checked again, now programmatically . <div>
将类'.checked'和radio设置为再次检查,现在以编程方式 。 Using preventDefault() on parent elements prevent the original event to be fired, but does not stop propagation. 在父元素上使用preventDefault()可以防止触发原始事件,但不会停止传播。 Understanding hierarchy and event propagation is crucial.
了解层次结构和事件传播至关重要。
You have part of the solution in your code snippet. 您的代码段中包含部分解决方案。 If you comment out that particular line, the code works properly, like you would expect.
如果您注释掉该特定行,则代码可以正常工作,就像您期望的那样。 But if you use
但如果你使用
e.stopPropagation();
it also works. 它也有效。
In order not to repeat information already on the web, I found a very similar case here ( Why does preventDefault() on a parent element's click 'disable' a checkbox? ) which may help you understand better event propagation and bubbling. 为了不重复网上已有的信息,我在这里找到了一个非常相似的案例( 为什么在父元素点击'禁用'一个复选框?上的preventDefault()?这可能有助于你理解更好的事件传播和冒泡。
You can also find an even better explanation here ( https://medium.freecodecamp.org/a-simplified-explanation-of-event-propagation-in-javascript-f9de7961a06e ). 您还可以在此处找到更好的解释( https://medium.freecodecamp.org/a-simplified-explanation-of-event-propagation-in-javascript-f9de7961a06e )。
MDN documentation also rarely fails to impress ( https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault ). MDN文档也很少令人印象深刻( https://developer.mozilla.org/en-US/docs/Web/API/Event/preventDefault )。
You just need to add e.stopPropagation()
to return the default functionality for radio button again which is checked
您只需要添加
e.stopPropagation()
以再次返回checked
单选按钮的默认功能
The behaviour is that You have radio
is a child to the div
and you click
listener is based on the parent div
and when you preventDefault
then the children inherit the prevention as well. 行为是你有
radio
是div
的孩子,你click
监听器是基于父div
,当你preventDefault
,孩子也继承了预防。
If the button is pressed on one element and released on a different one, the event is fired on the most specific ancestor element that contained both.
如果按下一个元素上的按钮并在另一个元素上释放,则会在包含这两个元素的最具体的祖先元素上触发该事件。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.