web-dev-qa-db-ja.com

マテリアルUIポップオーバー要素のオートフォーカスを防止します

ユーザーがクエリを入力すると更新される検索一致リストを作成しようとしています。ただし、入力要素にフォーカスを維持する方法がわかりません。ポップアップは常にフォーカスされます。 refを使用してプログラムでフォーカスを設定しようとしましたが、ステートレス関数コンポーネント(これが私の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

6
Chris Voss

これが発生する理由は、_<TextField>_でthis.showPopover(event)イベントが発生するたびにonChange={this.handleContactSearch.bind(this)}を呼び出しているためです。

これを修正するには、this.showPopover(event)を1回だけ呼び出す方法を見つける必要があります。

_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>
_

サンドボックス: 作業デモ

2
CaseyC

このアプローチの代替手段は、PopperClickAwayListener、およびBackdropコンポーネントを使用することです。 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>
  }
}

実用的な例ではありませんが、ポップオーバー/ポッパーを開いたまま入力を入力できるという問題を解決する方法を示しています。

2
Maciej Gurban

'disableAutoFocus'、 'disableEnforceFocus'小道具をポップオーバーに渡します。それは私のために働いた!

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

1
nymphadora