我正在尝试将TextField放入菜单中。除了文本字段为空并且我按下“ d”键而不是触发onChange事件之外,它大部分都起作用,它会跳到列表中的下一个MenuItem。
我尝试给Menu一个onKeyDown事件,并调用event.stopPropagation()和preventDefault,但是我认为它在MenuList上而不是Menu上。
function UserRequests(props) {
const [anchorEl, setAnchorEl] = React.useState(null)
const [filter, setFilter] = useState('')
const handleClick = e => setAnchorEl(e.currentTarget)
const handleClose = () => setAnchorEl(null)
const filteredUsers = props.pending.filter(x =>
x.user.name.includes(filter)
)
const handleFilterChange = e => {
e.preventDefault()
e.stopPropagation()
setFilter(e.target.value)
}
return (
<Fragment>
<Badge
color="secondary"
badgeContent={props.pending.length}
invisible={props.pending.length < 1}
>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
variant="outlined"
color="primary"
className={props.classes.button}
>
Pending Requests
</Button>
</Badge>
<Menu
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem button={false}>
<TextField
label="Filter"
value={filter}
fullWidth
onChange={handleFilterChange}
/>
</MenuItem>
{props.pending.length > 0 ? (
filteredMemebers.map(({ id, user }) => (
<MenuItem key={id} button={false}>
{user.name}
<ApproveUserButton
id={id}
domain={props.domain}
/>
<RemoveUserButton
id={id}
domain={props.domain}
/>
</MenuItem>
))
) : (
<MenuItem button={false}>No Pending Users</MenuItem>
)}
</Menu>
</Fragment>
)
}
预期结果:我在文本框中输入内容,它可以正常处理
实际:当我在文本框中键入内容时,其他处理程序在按下handleFilterChange之前正在使用某些按键
答案 0 :(得分:1)
您在停止onKeyDown
事件传播的正确轨道上,但是在这种情况下,您需要从TextField
组件本身而不是从Menu
停止传播组件。
下面的示例演示了这一点。 stopPropagation
方法包含一些额外的检查,以避免在菜单中禁用键盘焦点导航。此外,TextField的onKeyDown
上的MenuItem
允许使用 Tab 或向右箭头将焦点移到输入中进行键入。
import React from "react";
import Button from "@material-ui/core/Button";
import Menu from "@material-ui/core/Menu";
import MenuItem from "@material-ui/core/MenuItem";
import TextField from "@material-ui/core/TextField";
export default function SimpleMenu() {
const [anchorEl, setAnchorEl] = React.useState(null);
const [filter, setFilter] = React.useState("");
const filterRef = React.useRef();
function handleClick(event) {
setAnchorEl(event.currentTarget);
}
function handleClose() {
setAnchorEl(null);
}
const stopPropagation = e => {
switch (e.key) {
case "ArrowDown":
case "ArrowUp":
case "Home":
case "End":
break;
default:
e.stopPropagation();
}
};
const moveFocusToInput = e => {
if (e.key === "Tab" || e.key === "ArrowRight") {
e.stopPropagation();
e.preventDefault();
filterRef.current.focus();
}
};
return (
<div>
<Button
aria-controls="simple-menu"
aria-haspopup="true"
onClick={handleClick}
>
Open Menu
</Button>
<Menu
id="simple-menu"
anchorEl={anchorEl}
keepMounted
open={Boolean(anchorEl)}
onClose={handleClose}
>
<MenuItem button={false} onKeyDown={moveFocusToInput}>
<TextField
inputRef={filterRef}
label="Filter"
value={filter}
onKeyDown={stopPropagation}
onChange={e => setFilter(e.target.value)}
/>
</MenuItem>
<MenuItem onClick={handleClose}>Profile</MenuItem>
<MenuItem onClick={handleClose}>My account</MenuItem>
<MenuItem onClick={handleClose}>Logout</MenuItem>
</Menu>
</div>
);
}
请注意,您不想在preventDefault
的{{1}}事件上调用onKeyDown
,因为那样会阻止TextField
事件的触发。