简体   繁体   English

包装在单选按钮上的标签标签阻止单选按钮响应JavaScript中的“更改”事件侦听器

[英]A label tag wrapped around a radio button prevents the radio button from responding to a “change” event listener in JavaScript

Problem 问题

I have some dynamically generated HTML (using JavaScript) that contains a form with some radio buttons in it. 我有一些动态生成的HTML(使用JavaScript),其中包含带有一些单选按钮的表单。 I added event listeners (using "change" ) to all of the radio buttons to call a function whenever their value is changed. 我将事件侦听器(使用"change" )添加到所有单选按钮,以在其值更改时调用函数。 I am already aware that this event only triggers when a button's " checked " value goes from false to true , and not the other way around. 我已经知道,此事件仅在按钮的“ checked ”值从false变为true时触发,而在其他情况下不会触发。

To simplify my code, I've wrapped the label tags around the input tags to avoid having to generate a bunch of unique id's for my radio buttons. 为了简化代码,我将label标签包裹在input标签周围,以避免必须为单选按钮生成一堆唯一的ID。 However, when the label tags are wrapped around the radio inputs rather than sitting in the same scope as the radio inputs, the "change" event listener does not respond, even when clicking directly on the button itself. 但是,当label标签包裹无线电输入周围而不是与无线电输入位于同一作用域时,即使直接单击按钮本身,“更改”事件侦听器也不会响应。

Examples 例子

I put together a jsfiddle example to show what I'm talking about. 我整理了一个jsfiddle示例来说明我在说什么。 JS Fiddle Example The first group (that doesn't work) is generated this way: JS Fiddle示例第一个组(无效)是通过以下方式生成的:

for (var i = 0; i < 3; i++)
{
    var label = document.createElement("label");
    var radio = document.createElement("input");
    radio.setAttribute("type", "radio");
    radio.setAttribute("name", "group1");

    radio.addEventListener("change", function()
    {
        alert("group1 changed!")
    }, false);

    label.appendChild(radio);
    label.innerHTML += "Radio " + (i + 1);
    var br = document.createElement("br");
    g1.appendChild(label);
    g1.appendChild(br);
}

And the second group (that does work) is generated this way: 第二组(起作用的)是这样生成的:

for (var i = 0; i < 3; i++)
{
    var radio = document.createElement("input");
    radio.setAttribute("type", "radio");
    radio.setAttribute("name", "group2");
    radio.setAttribute("id", "g2r" + i);

    radio.addEventListener("change", function()
    {
        alert("group2 changed!")
    }, false);

    var label = document.createElement("label");
    label.setAttribute("for", "g2r" + i);
    label.innerHTML = "Radio " + (i + 1);
    var br = document.createElement("br");
    g2.appendChild(radio);
    g2.appendChild(label);
    g2.appendChild(br);
}

Question

Is this an known bug or something? 这是已知的错误还是什么? And is there some kind of workaround? 是否有某种解决方法? I'd like to keep the wrapped labels because it's easier to generate, and I think it's cleaner, but not at the expense of functionality, obviously. 我想保留包装好的标签,因为它更易于生成,而且我认为它更干净,但显然不能以牺牲功能为代价。

Thank you! 谢谢!

I removed the line: 我删除了这一行:

    label.innerHTML += "Radio " + (i + 1);

from your jsFiddle and that fixes the issue. 从您的jsFiddle中解决了该问题。 The reason this is breaking your code is that when you use innerHTML to add something to inside another element, what you're really doing is replacing all of the contents of that element. 破坏代码的原因是,当您使用innerHTML在另一个元素内添加内容时,您真正要做的是替换该元素的所有内容。 Sure, when you use += you're keeping what was there before and adding to it, but you're still essentially copying the contents out, adding to them, and then creating NEW DOM ELEMENTS for all the html you're adding back in -- whether it's the old contents or the new. 当然,当您使用+ =时,您将保留之前的内容并添加到其中,但是实际上您仍在复制内容,添加到其中,然后为要添加的所有html创建新的DOM ELEMENTS in-无论是旧内容还是新内容。 This means that any handlers bound to the old contents will be lost, since you're overwriting them with new DOM elements. 这意味着绑定到旧内容的所有处理程序都将丢失,因为您正在用新的DOM元素覆盖它们。

If you replace that line with this: 如果您用以下内容替换该行:

    label.appendChild(document.createTextNode("Radio " + (i + 1)));

That'll append the new text node you're creating without removing and recreating any of your existing elements, so your handlers will still be there! 这将追加您正在创建的新文本节点,而不会删除并重新创建任何现有元素,因此您的处理程序仍将在那里! Here's a working jsFiddle: http://jsfiddle.net/335cQ/13/ . 这是一个有效的jsFiddle: http : //jsfiddle.net/335cQ/13/

radio.setAttribute("id", "rb");

<style>
#rb
{
    z-index:5;
}
</style>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM