MenuItem中的TextField-onKeyDown事件会干扰TextField中的onChange [英] TextField in MenuItem - onKeyDown event interfering with onChange in TextField
问题描述
我正在尝试将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(空)constfilteredUsers = props.pending.filter(x =>x.user.name.includes(过滤器))const handleFilterChange = e =>{e.preventDefault()e.stopPropagation()setFilter(e.target.value)}返回 (<片段><徽章color ="secondary"badgeContent = {props.pending.length}invisible = {props.pending.length<1}><按钮aria-controls =简单菜单"aria-haspopup ="true"onClick = {handleClick}variant ="outlined"color ="primary"className = {props.classes.button}>待处理的请求</按钮></徽章><菜单anchorEl = {anchorEl}keepMountedopen = {Boolean(anchorEl)}onClose = {handleClose}>< MenuItem button = {false}>< TextFieldlabel =过滤器"值= {过滤器}全屏宽度onChange = {handleFilterChange}/></MenuItem>{props.pending.length>0?(filteredMemebers.map((({id,user})=>(< MenuItem key = {id} button = {false}>{用户名}< ApproveUserButtonid = {id}域= {props.domain}/>< RemoveUserButtonid = {id}域= {props.domain}/></MenuItem>))):(< MenuItem button = {false}>没有待处理的用户</MenuItem>)}</菜单></片段>)}
预期结果:我在文本框中输入内容,并且可以正常处理
实际:当我在文本框中键入内容时,其他处理程序在按下handleFilterChange之前正在使用某些按键
您在正确的轨道上,停止了 onKeyDown
事件的传播,但是在这种情况下,您需要停止从 TextField
组件本身,而不是 Menu
组件.
下面的示例演示了这一点. stopPropagation
方法包含一些额外的检查,以避免在菜单中禁用键盘焦点导航.此外,TextField的 MenuItem
上的 onKeyDown
允许使用 Tab 或向右箭头将焦点移到输入中进行键入.
import从反应"中反应;从"@ material-ui/core/Button"导入Button;从"@ material-ui/core/Menu"导入菜单;从@material-ui/core/MenuItem"导入菜单项;从"@ material-ui/core/TextField"导入TextField;导出默认函数SimpleMenu(){const [anchorEl,setAnchorEl] = React.useState(null);const [filter,setFilter] = React.useState(");const filterRef = React.useRef();函数handleClick(event){setAnchorEl(event.currentTarget);}函数handleClose(){setAnchorEl(null);}const stopPropagation = e =>{开关(e.key){案例"ArrowDown":案例"ArrowUp":案例家":情况结束":休息;默认:e.stopPropagation();}};const moveFocusToInput = e =>{if(e.key ==="Tab" || e.key ==="ArrowRight"){e.stopPropagation();e.preventDefault();filterRef.current.focus();}};返回 (< div><按钮aria-controls =简单菜单"aria-haspopup ="true"onClick = {handleClick}>开启选单</按钮><菜单id =简单菜单"anchorEl = {anchorEl}keepMountedopen = {Boolean(anchorEl)}onClose = {handleClose}>< MenuItem button = {false} onKeyDown = {moveFocusToInput}>< TextFieldinputRef = {filterRef}label =过滤器"值= {过滤器}onKeyDown = {stopPropagation}onChange = {e =>setFilter(e.target.value)}/></MenuItem>< MenuItem onClick = {handleClose}>个人资料</MenuItem>< MenuItem onClick = {handleClose}>我的帐户</MenuItem>< MenuItem onClick = {handleClose}>注销</MenuItem></菜单></div>);}
请注意,您不想在 TextField
的 onKeyDown
事件上调用 preventDefault
,因为那样会阻止触发onChange
事件.
I'm am trying to put a TextField in a Menu. It works for the most part except if the text field is empty and i press the "d" key instead of firing the onChange event it skips to the next MenuItem in the list.
I tried giving the Menu an onKeyDown event and calling event.stopPropagation() and preventDefault but I think its on the MenuList not the 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>
)
}
Expected Result: I type in the textbox and it handles normaly
Actual: When i type in the textbox some key presses are being used by other handlers before they hit my handleFilterChange
You're on the right track with stopping propagation of the onKeyDown
event, but in this case you need to stop propagation from the TextField
component itself, rather than from the Menu
component.
The example below demonstrates this. The stopPropagation
method contains some extra checks to avoid disabling keyboard focus navigation in the menu. Also the onKeyDown
on the TextField's MenuItem
allows using Tab or Right Arrow to move focus into the input for typing.
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>
);
}
Note that you don't want to call preventDefault
on the onKeyDown
event of the TextField
, since that will prevent the onChange
event from firing.
这篇关于MenuItem中的TextField-onKeyDown事件会干扰TextField中的onChange的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!