reactjs - 在 ReactBootstrapTypeahead 中选择中间匹配的项目
问题描述
在我的 ReactBootstrapTypeahead 组件中,我可以单击任何选项来选择它,但是Tab如果它在字符串的开头匹配,则 using 只会选择第一个选项。如果第一个选项在中间匹配,则点击Tab仅移动焦点而不选择选项。如果您首先使用箭头键突出显示该选项,它确实有效。
每个选项都包含一个id
,make
和model
, 并且我将最后两个组合成name
(eg 'Toyota Prius'
) 以供labelKey
. 一切正常,除了选择第一项而不使用箭头键突出显示它。
<AsyncTypeahead
id="search"
selectHintOnEnter
labelKey="name"
filterBy={startsWith}
renderMenu={renderMenu}
options={results}
/>
我正在使用自定义renderMenu
函数对选项进行分组...
const renderMenu = (results, menuProps) => {
const items = [];
let makesHeader, lastMake, idx = 0;
results.forEach(result => {
const { id, make, model } = result;
if (!make) {
// skip "click to load more..." text
items.push(
<Menu.Header key="more-header">
More Results Hidden…
</Menu.Header>
);
}
else if (!model) {
if (!makesHeader) {
items.push(
<Menu.Header key="makes-header">
Makes
</Menu.Header>
);
makesHeader = true;
}
items.push(
<MenuItem key={id} option={result} position={idx}>
<WordHighlighter search={menuProps.text}>
{make}
</WordHighlighter>
</MenuItem>
);
}
else {
if (make !== lastMake) {
items.push(
<Menu.Header key={`${make}-header`}>
{make}
</Menu.Header>
);
lastMake = make;
}
items.push(
<MenuItem key={id} option={result} position={idx}>
<WordHighlighter search={menuProps.text}>
{model}
</WordHighlighter>
</MenuItem>
);
}
idx++;
});
return <Menu {...menuProps}>{items}</Menu>;
};
...并且仅在任何单词的开头突出显示匹配项。
const WordHighlighter = props => {
const search = props.search.toLowerCase(),
len = search.length,
parts = [];
let count = 0;
props.children.split(' ').forEach(word => {
if (word.toLowerCase().startsWith(search)) {
parts.push(<mark className="rbt-highlight-text"
key={++count}>{word.substr(0, len)}</mark>);
parts.push(<span key={++count}>{word.substr(len) + ' '}</span>);
}
else {
parts.push(<span key={++count}>{word + ' '}</span>);
}
});
return <span>{parts}</span>;
};
解决方案
我通过用我自己的覆盖 Typeahead 的onKeyDown
回调解决了这个问题。
const typeahead = useRef();
const onChange = useCallback(([ result ]) => {
typeahead.current.getInstance().clear();
typeahead.current.getInstance().blur();
history.push(`/cars/${result.slug}`);
}, [ typeahead ]);
useEffect(() => {
const instance = typeahead.current.getInstance(),
original = instance._handleKeyDown;
instance._handleKeyDown = (e, results, isMenuDown) => {
if (results && results.length && (e.key === 'Enter' || e.key === 'Tab')) {
e.preventDefault();
e.stopPropagation();
onChange(results);
}
else {
return original(e, results, isMenuDown);
}
};
}, [ typeahead, onChange ]);
推荐阅读
- mysql - 替换几个条目
- c# - WCF / WCF Ria 服务在“IncludedResults”中返回关系数据
- php - 如何使用 php 通过 url 参数访问单个 json 帖子?
- xslt - 元素中的 XPath
- c# - 如何在不更改构造函数逻辑的情况下计算实例?[更新]
- mysql - Yii框架中如何解决CDb连接错误
- reactjs - 如何将 antd design 中的 popconfirm 添加到文件删除操作中
- java - SendFailedException.getValidUnsentAddresses()
- ios - 我正在使用此代码弹出一个带有取消和提交选项的文本字段,但键盘也在显示。我不想显示键盘
- json - 使用 Python 脚本将包含 json 对象列表的 .json 文件上传到 Azure CosmosDB 时出现问题