ユーザーがクエリを入力すると更新される検索一致リストを作成しようとしています。ただし、入力要素にフォーカスを維持する方法がわかりません。ポップアップは常にフォーカスされます。 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
これが発生する理由は、_<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>
_
サンドボックス: 作業デモ
このアプローチの代替手段は、Popper
、ClickAwayListener
、および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>
}
}
実用的な例ではありませんが、ポップオーバー/ポッパーを開いたまま入力を入力できるという問題を解決する方法を示しています。
'disableAutoFocus'、 'disableEnforceFocus'小道具をポップオーバーに渡します。それは私のために働いた!