MenuItem中的TextField-onKeyDown事件会干扰TextField中的onChange

时间:2019-07-11 18:18:26

标签: material-ui

我正在尝试将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之前正在使用某些按键

1 个答案:

答案 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>
  );
}

Edit TextField in MenuItem

请注意,您不想在preventDefault的{​​{1}}事件上调用onKeyDown,因为那样会阻止TextField事件的触发。