我正在尝试创建一个搜索匹配列表,该列表会随着用户在其查询中键入而更新。但是,我不知道如何保持对输入元素的关注。弹出窗口总是会集中注意力。我曾尝试使用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元素保持焦点,以便用户可以输入查询而不会中断?
答案 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)
此方法的替代方法是使用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>
}
}
不是一个有效的示例,但是显示了如何解决在打开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>