防止材质用户界面弹出框元素自动聚焦

时间:2018-07-17 18:34:33

标签: javascript css reactjs material-ui

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

这是行为的形象。 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

3 个答案:

答案 0 :(得分:2)

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

为解决此问题,您将需要找到一种仅调用一次this.showPopover(event)的方法。

我可以结合使用autoFocus={true}onFocus={this.showPopover}上的<TextField/>事件来使其工作。唯一的问题是,当您第一次打开模式时,弹出框将显示为空。我在文本字段上使用了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>

沙箱:Working Demo

答案 1 :(得分:0)

此方法的替代方法是使用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的同时能够输入输入的问题。

答案 2 :(得分:0)

您可以将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>