繁体   English   中英

防止 material-ui 弹出元素的自动聚焦

[英]Prevent auto focus of a material-ui popover element

我正在尝试创建一个搜索匹配列表,该列表会随着用户在查询中键入而更新。 但是,我无法弄清楚如何保持对输入元素的关注。 弹出窗口总是聚焦。 我曾尝试使用 refs 以编程方式设置焦点,但我无法为无状态函数组件(我假设这是我的 TextField 输入)提供 ref。

这是行为的 gif。 https://imgur.com/a/JVskedr

请注意弹出窗口如何窃取焦点并阻止用户进一步输入。

<TextField
              id='contact'
              label='Contact Name'
              className={classes.textField}
              margin='normal'
              ref={this.nameInput}
              onChange={this.handleContactSearch.bind(this)}
              value={this.state.contactSearch}
            />
            <Popover
              open={Boolean(anchorEl)}
              anchorEl={anchorEl}
              onClick={this.handlePopoverClose}
              anchorOrigin={{
                vertical: 'bottom',
                horizontal: 'center'
              }}
              transformOrigin={{
                vertical: 'top',
                horizontal: 'center'
              }}
              autoFocus={false}
            >
              <List>{this.createContactList()}</List>
            </Popover>

这些是相关的功能:

  handleContactSearch(event) {
    this.handlePopoverClick(event);
    this.setState({ contactSearch: handleText(event) });
    this.props.filterContacts(
      event.target.value,
      this.props.accountInfo.AccountName
    );
  }
  handlePopoverClick = event => {
    this.setState({
      anchorEl: event.currentTarget
    });
  };

  handlePopoverClose = () => {
    this.setState({
      anchorEl: null
    });
  };

如何使 TextField 元素保持焦点,以便用户可以不间断地输入查询?

沙盒: https : //codesandbox.io/s/mjqoj9lxkj

将“disableAutoFocus”、“disableEnforceFocus”道具传递给您的弹出框。 它对我有用!

<Popover
 open={Boolean(anchorEl)}

 // pass these props to the popover component
 disableAutoFocus={true}
 disableEnforceFocus={true}
 >

https://material-ui.com/api/modal/

发生这种情况的原因是每次在您的<TextField>触发onChange={this.handleContactSearch.bind(this)}事件时,您都会调用this.showPopover(event)

为了解决这个问题,您需要找到一种方法,只调用一次this.showPopover(event)

我能够使用<TextField/>上的autoFocus={true}onFocus={this.showPopover}事件的组合使其工作。 唯一的问题是当您第一次打开模态时,弹出窗口将显示为空。 我在文本字段上使用了ref并使用了条件来设置弹出框的不透明度,因此它仅在文本字段中有值时才显示。

也许不是最终的解决方案,但它有效,至少应该让你朝着正确的方向前进。

<div className={classes.paper}>
    <TextField
        id="contact123"
        label="Contact Name"
        className={classes.textField}
        margin="normal"
        onChange={this.handleContactSearch.bind(this)}
        value={this.state.contactSearch}
        autoFocus={true}
        onFocus={this.showPopover}
        inputRef={input => (this.tf = input)}
    />
    <Popover
        open={Boolean(anchorEl)}
        anchorEl={document.getElementById("contact123")}
        onClick={this.closePopover}
        anchorOrigin={{
            vertical: "bottom",
            horizontal: "center"
        }}
        transformOrigin={{
            vertical: "top",
            horizontal: "center"
        }}
        style={{ opacity: this.tf && !this.tf.value.length ? 0 : 1 }}
    >
        <List>{this.state.contactSearch}</List>
    </Popover>
    <div>
        <Button color="primary" className={classes.saveButton}>
            Save
        </Button>
    </div>
</div>

沙盒:工作演示

这种方法的替代方法是使用PopperClickAwayListenerBackdrop组件。 使用Popper可以让您专注于输入字段并继续输入。 解决方案大致如下:

class Foo extends React.Component {
  inputRef = React.createRef(),

  render() {
    const { open, searchValue } = this.state

    <RootRef rootRef={this.inputRef}>
      <div className={classes.container}>
        // You may be able to use TextField as well
        <FormControl
          onKeyDown={//set open = false}
          onClick={// set open = true (e.g. only when searchValue !== '' }
        >
          <InputBase
            value={searchValue}
            onChange={this.handleSearchValueChange}
            inputRef={this.inputRef}
          />
        </FormControl>
        <Popper anchorEl={this.inputRef.current} open={open} >
          <ClickAwayListener onClick={//set open = false} onClickAway={//set open = false}>
            Popover content
          </ClickAwayListener>
        </Popper>
      </div>
    </RootRef>
  }
}

不是一个工作示例,但展示了如何解决在打开 popover/popper 时能够输入输入的问题。

您可以将 onKeyDown 属性添加到每次用户键入时将关闭它的弹出窗口,并将 onKeyUp 属性添加到再次弹出弹出窗口的搜索输入。 不是最好的解决方案,但它对我有用。

<InputBase
              autoFocus={true}
              value={searchText}
              onChange={(e) => handleSearch(e)}
              onKeyUp={e => setAnchorEl(e.currentTarget)}
              placeholder="Search…"
              classes={{
                root: classes.inputRoot,
                input: classes.inputInput,
              }}
              inputProps={{ "aria-label": "search" }}
            />
            {searchResult && (
              <Popover
              disableAutoFocus 
              className={classes.pop}
              onKeyDown={handleClose}
                id={id}
                open={open}
                anchorEl={anchorEl}
                onClose={handleClose}
                anchorOrigin={{
                  vertical: "bottom",
                  horizontal: "center",
                }}
                transformOrigin={{
                  vertical: "top",
                  horizontal: "center",
                }}
              >
                {searchResult.map((song, i) => {
                  return (
                      <Link to={`/Songs/${song.unique_id}?Artist=${song.artist_id}`}>
                    <ListItem>
                    <IconButton variant="h6" >
                      <PlayCircleFilledRounded/>
                    </IconButton>
                      {song.title}
                      </ListItem>
                      </Link>
                  );
                })}
              </Popover>
            )}
          </div>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM