fluent UI 9 中的Combobox如何在它自带的input框下面,option的上面,再加一个用于search的input框
会出现一个问题,点击search input框,可以触发input的onClick事件,但是无法获取焦点,焦点还在select的下拉框中
这种情况是由于 Combobox 的默认行为或者事件冒泡导致的。
解决方法:
const inputRef = React.useRef<any>(null);
<Combobox
aria-labelledby={comboId}
placeholder="Select an animal"
open={isOpen}
onOpenChange={(event, data) => {
setIsOpen(data.open);
console.log(data.open, isOpen, 'setIsOpen');
}}
{...props}
onClick={() => setIsOpen(true)} // 点击 Combobox 保持下拉框打开
>
<Input
contentBefore={<SearchRegular />}
ref={inputRef}
onClick={(ev) => {
ev.stopPropagation();
inputRef.current?.focus();
setIsOpen(true); // 点击 Input 保持下拉框打开
console.log(ev, 'Input clicked');
}}
/>
{options.map((option) => (
<Option key={option} disabled={option === 'Ferret'}>
{option}
</Option>
))}
</Combobox>
首先在input的唯一可以触发的onClick方法中取消默认冒泡行为,(此时onFocus,onChange事件都不会触发)
然后强制设置焦点,在 onClick 事件中,手动将焦点设置到 Input 元素上,通过ref,走到这一步会发现点击input之后,下拉框消失了,这时候就要用到Combobox的open属性,点击input后,设置open的值一直是打开状态。使用onOpenChange,监听当点击其他地方时的监听事件。
这样就可以输入了,其他操作也会很流畅。
可以在官网链接测试
https://stackblitz.com/edit/9jdz2a-yxlsnb?file=src%2Fexample.tsx
完整代码
import * as React from 'react';
import {
Combobox,
makeStyles,
Option,
useId,
Input,
} from '@fluentui/react-components';
import { SearchRegular } from '@fluentui/react-icons';
import type { ComboboxProps } from '@fluentui/react-components';
const useStyles = makeStyles({
root: {
// Stack the label above the field with a gap
display: 'grid',
gridTemplateRows: 'repeat(1fr)',
justifyItems: 'start',
gap: '2px',
maxWidth: '400px',
},
});
export const Default = (props: Partial<ComboboxProps>) => {
const comboId = useId('combo-default');
const [isOpen, setIsOpen] = React.useState(false);
const options = ['Cat', 'Dog', 'Ferret', 'Fish', 'Hamster', 'Snake'];
const styles = useStyles();
const inputRef = React.useRef<any>(null);
return (
<div className={styles.root}>
<label id={comboId}>Best pet</label>
<Combobox
aria-labelledby={comboId}
placeholder="Select an animal"
open={isOpen}
onOpenChange={(event, data) => {
setIsOpen(data.open);
console.log(data.open, isOpen, 'setIsOpen');
}}
{...props}
onClick={() => setIsOpen(true)} // 点击 Combobox 保持下拉框打开
>
<Input
contentBefore={<SearchRegular />}
ref={inputRef}
onClick={(ev) => {
ev.stopPropagation();
inputRef.current?.focus();
setIsOpen(true); // 点击 Input 保持下拉框打开
console.log(ev, 'Input clicked');
}}
/>
{options.map((option) => (
<Option key={option} disabled={option === 'Ferret'}>
{option}
</Option>
))}
</Combobox>
</div>
);
};