首页 > 解决方案 > 自动完成中的 React Material UI 打开模式失去焦点

问题描述

我正在使用material-ui lib,我需要一个自动完成功能,其中自动完成功能中的每个项目都是可点击的并打开一个模式。

一般结构如下:

const ModalBtn = () => {
    ...
    return (
        <>
            <button ... (on click set modal to open)
            <Modal ...
        </>

    );
}

const AutoCompleteWithBtns = () => {
    return (
        <Autocomplete
            renderTags={(value, getTagProps) =>
                value.map((option, index) => <ModalBtn />)
            }
            ...
        />
    );

}

注意,ModalBtn 是一个组件,不能分为 Button 和 Modal 两个组件。

问题是,当您单击模态内的按钮时 - 焦点保持在自动完成内,并且模态将永远不会获得焦点(如果我在模态内有输入 - 我不能在里面写任何东西)。

尝试了所有标准的自动完成/模态焦点相关道具(disableEnforceFocus,disableEnforceFocus等...),但没有任何效果。

这是一个有效的代码框示例。如您所见 - 如果您单击不在自动完成组件内的按钮 - 一切正常(您可以在输入字段内添加文本)。如果您单击自动完成内的按钮 - 模式内的输入字段不可编辑(您失去焦点)。

这是该问题的一个示例:
在此处输入图像描述

标签: javascriptreactjsautocompletemodal-dialogmaterial-ui

解决方案


Modal从 内部渲染的问题Autocomplete是事件从 传播ModalAutocomplete。特别是,单击和鼠标按下事件的处理Autocomplete方式都会导致您的情况出现问题。这主要是为了在您与Autocomplete.

下面(来自https://github.com/mui-org/material-ui/blob/v4.9.11/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js#L842)是Autocomplete代码的一部分妨碍你:

  // Prevent input blur when interacting with the combobox
  const handleMouseDown = (event) => {
    if (event.target.getAttribute('id') !== id) {
      event.preventDefault();
    }
  };

  // Focus the input when interacting with the combobox
  const handleClick = () => {
    inputRef.current.focus();

    if (
      selectOnFocus &&
      firstFocus.current &&
      inputRef.current.selectionEnd - inputRef.current.selectionStart === 0
    ) {
      inputRef.current.select();
    }

    firstFocus.current = false;
  };

当鼠标按下事件发生在可聚焦元素上时,默认浏览器行为是让该元素接收焦点,但用于Autocomplete调用的鼠标按下处理程序event.preventDefault()会阻止此默认行为,从而防止鼠标按下事件改变焦点(因此焦点停留在Modal自身上,如其蓝色焦点轮廓所示)。但是,您可以使用 tab 键成功地将焦点移动到 Modal 的 TextField,因为没有什么可以阻止焦点更改的机制。

即使您Autocomplete单击. 当您打开时,这样做的效果是,当您单击 时,焦点会短暂移动到输入元素,但由于其“强制焦点”功能,焦点会立即返回到。如果您将属性添加到,您会看到当您单击(例如在 TextField 上)时,光标仍保留在.AutocompleteAutocompleteModalModalAutocompleteModaldisableEnforceFocusModalModalAutocomplete

解决方法是确保这两个事件不会传播到Modal. 通过调用event.stopPropagation()上的单击和鼠标按下事件,ModalAutocomplete这些事件发生在Modal.

      <Modal
        onClick={event => event.stopPropagation()}
        onMouseDown={event => event.stopPropagation()}
        ...

在自动完成中编辑模式

相关答案:如何在 Material UI Labs Autocomplete 中创建可点击的第一个选项


推荐阅读