选中< legend>中的onChange复选框内部禁用< fieldset>不使用React在Firefox中触发 [英] checkbox onChange in <legend> inside disabled <fieldset> not firing in Firefox with React

查看:31
本文介绍了选中< legend>中的onChange复选框内部禁用< fieldset>不使用React在Firefox中触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下内容可在Firefox 80.0和Chromium 84.0.4147.89中使用.

The following works in Firefox 80.0 and Chromium 84.0.4147.89.

const fieldset = document.getElementById("fieldset");
const toggle = document.getElementById("toggle");

toggle.addEventListener("change", () => {
  if (fieldset.hasAttribute("disabled")) {
    fieldset.removeAttribute("disabled");
  } else {
    fieldset.setAttribute("disabled", true);
  }
});

<form action="#">
  <fieldset id="fieldset">
    <legend>
      <label>toggle <input id="toggle" type="checkbox" /></label>
    </legend>
    <input />
  </fieldset>
</form>

但是,当我尝试在React中执行类似的操作时,它在Firefox中不起作用.禁用字段集后,onChange事件似乎不会触发.

However, when I try and do something similar in React, it doesn't work in Firefox. The onChange event appears not to fire once the fieldset is disabled.

function App() {
  const [disabled, setDisabled] = React.useState(false);
  const toggleDisabled = React.useCallback(() => {
    setDisabled((disabled) => !disabled);
  }, []);

  return (
    <form action="#">
      <fieldset disabled={disabled}>
        <legend>
          <label>
            toggle <input onChange={toggleDisabled} type="checkbox" />
          </label>
        </legend>
        <input />
      </fieldset>
    </form>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>

MDN字段集文章说:

[当禁用fieldset元素时]请注意,不会禁用< legend> 元素内的表单元素.

W3C(示例B)

W3C (Example B) and WHATWG also mention that the contents of the <legend> should not be disabled.

因此,我认为这两段代码的行为应相同:我应该能够使用复选框切换 disabled 属性.

So I believe that the two pieces of code should behave in the same way: I should be able to toggle the disabled attribute using the checkbox.

如何在Firefox 80.0+上的React中实现相同的效果?

How can I achieve the same effect in React on Firefox 80.0+?

推荐答案

根据该段前面两行的内容,浏览器似乎期望这种行为.

This behavior seems expected by the browser according to 2 lines earlier in that paragraph.

disabled 如果设置了此布尔属性,则所有作为< fieldset> 的后代的表单控件都将被禁用,这意味着它们不可编辑并且不会与一起提交.他们不会收到任何浏览事件,例如鼠标单击或与焦点相关的事件.默认情况下,浏览器将此类控件显示为灰色.请注意,元素内的表单元素不会被禁用.- MDN

disabled If this Boolean attribute is set, all form controls that are descendants of the <fieldset>, are disabled, meaning they are not editable and won't be submitted along with the . They won't receive any browsing events, like mouse clicks or focus-related events. By default browsers display such controls grayed out. Note that form elements inside the element won't be disabled. - MDN

似乎Firefox确实按照其应有的方式执行了操作.
此处的解决方案是将< input> 放置在字段集之外,以使其不受 disabled 属性的影响.

It seems that Firefox does exactly what it describes that it should do.
A solution here would be to just place the <input> outside of the fieldset so that it won't be affected by the disabled property.

您对侦听DOM中更高级别事件的评论使我开始思考.如果您通过将您自己的事件侦听器与良好的 addEventListener 绑定并结合 useRef useEffect 钩子来绕过它,该怎么办?创建对复选框的引用,并在第一次渲染后侦听change事件.现在事件正在监听输入本身.
这种变通方法"是指,确实可以在FF中使用.

Your comment about listening for the events higher up in the DOM got me to thinking. How about if you bypass that by binding your own event listener with good ol' addEventListener, in combination with the useRef and useEffect hooks. Create a reference to the checkbox and to listen for the change event after the first render. Now the event is listening to the input itself.
This "workaround" does seem to work in FF.

function App() {
  const [disabled, setDisabled] = React.useState(false);
  const toggleElement = React.useRef(null)
  const toggleDisabled = React.useCallback(() => {
    setDisabled(disabled => !disabled);
  }, []);
  
  React.useEffect(() => {
    toggleElement.current.addEventListener('change', toggleDisabled);
  }, []);

  return (
    <form action="#">
      <fieldset disabled={disabled}>
        <legend>
          <label>
          toggle <input ref={toggleElement} type="checkbox" />
      </label>
        </legend>
        <input />
      </fieldset>
    </form>
  );
}

ReactDOM.render(<App />, document.getElementById("root"));

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>

<div id="root"></div>

这篇关于选中&lt; legend&gt;中的onChange复选框内部禁用&lt; fieldset&gt;不使用React在Firefox中触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆