从自动完成内起React Material UI打开模式失去焦点 [英] React Material UI open modal from within autocomplete lose focus
问题描述
我正在使用material-ui lib,我需要具有一个自动完成功能,其中可以单击该自动完成功能中的每个项目并打开一个模式.
通常的结构是:
const ModalBtn =()=>{...返回 (<><按钮...(在点击时将模式设置为打开)<模态...</>);}const AutoCompleteWithBtns =()=>{返回 (<自动完成renderTags = {(value,getTagProps)=>value.map((option,index)=>< ModalBtn/>)}.../>);}
请注意,ModalBtn是不能分为Button和Modal两个组件的组件.
问题是,当您单击模式内的按钮时-焦点将保留在自动完成功能内,而模式将永远不会获得焦点(如果我在模式内有输入-我无法在其中输入任何内容).
尝试了所有与自动完成/模式焦点相关的标准道具( disableEnforceFocus
, disableEnforceFocus
等),但没有任何效果.
这是一个
从 Autocomplete
内部呈现 Modal
的问题是事件从传播>模式
到自动完成
.特别是,单击和鼠标按下事件均由 Autocomplete
处理,从而导致您遇到的问题.这主要是为了在您与自动完成
的不同部分进行交互时将焦点保持在正确的位置.
下面(来自
相关答案:working codesandbox example. As you can see - if you click on the button that is not inside the autocomplete component - everything works (you can add text inside the input field). If you click on the button that is inside the autocomplete - the input field inside the modal is not editable (you lose focus).
Here is an example of the issue:
The problem with having the Modal
rendered from within the Autocomplete
is that events propagate from the Modal
to the Autocomplete
. In particular, click and mouse-down events are both handled by Autocomplete
in a manner that causes problems in your case. This is primarily logic intended to keep focus in the right place as you interact with different parts of the Autocomplete
.
Below (from https://github.com/mui-org/material-ui/blob/v4.9.11/packages/material-ui-lab/src/useAutocomplete/useAutocomplete.js#L842) is the portion of the Autocomplete
code that is getting in your way:
// 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;
};
The default browser behavior when a mouse down event occurs on a focusable element is for that element to receive focus, but the mouse-down handler for Autocomplete
calls event.preventDefault()
which prevents this default behavior and thus prevents a focus change from the mouse-down event (so focus stays on the Modal
itself as indicated by its blue focus outline). You can however successfully move focus to the Modal's TextField using the tab key, since nothing is preventing that mechanism of focus change.
The Autocomplete
click handler is keeping focus on the input of the Autocomplete
even if you click some other part of the Autocomplete
. When your Modal
is open, the effect of this is that when you click in the Modal
, focus is moved briefly to the Autocomplete
input element, but the focus is immediately returned to the Modal
due to its "enforce focus" functionality. If you add the disableEnforceFocus
property to the Modal
, you'll see that when you click in the Modal
(e.g. on the TextField) the cursor remains in the input of the Autocomplete
.
The fix is to make sure that these two events do NOT propagate beyond the Modal
. By calling event.stopPropagation()
for both the click and mouse-down events on the Modal
, it prevents the Autocomplete
functionality for these two events from being executed when these events occur within the Modal
.
<Modal
onClick={event => event.stopPropagation()}
onMouseDown={event => event.stopPropagation()}
...
Related answer: How can I create a clickable first option in Material UI Labs Autocomplete
这篇关于从自动完成内起React Material UI打开模式失去焦点的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!