MenuItem中的TextField-onKeyDown事件会干扰TextField中的onChange [英] TextField in MenuItem - onKeyDown event interfering with onChange in TextField

查看:60
本文介绍了MenuItem中的TextField-onKeyDown事件会干扰TextField中的onChange的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将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屋!

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