【发布时间】:2021-07-02 18:42:51
【问题描述】:
我创建了一个自定义自动完成下拉列表,但我需要强制用户从列表中选择一些内容,同时保持在输入字段中输入内容的可能性。
如何创建这样的验证?自动完成组件是一个列表,可以从 API 中选择一个东西,但用户仍然可以在输入字段中输入任何内容并发送它。我希望用户只能使用建议的项目提交表单。你能帮我解决这个问题吗?
基本上问题是:如何检查输入值是否与从自动完成组件中获取的项目相同?
export type AutocompletePropsType = {
inputValue: string;
currentIndex: number;
onSelect: (selectedItem: string, slug?: string | null) => void;
hasError: boolean;
list: AutocompleteResponse['data'];
};
type PropsType = {
onChange: (value: string, type: string, isValid?: boolean, slug?: string) => void;
inputName: string;
type: InputType;
label: string;
autocompleteComponent: React.ComponentType<AutocompletePropsType>;
validator?: UseFieldValidatorType;
};
const SearchInput = (props: PropsType): JSX.Element => {
const { onChange, inputName, type, label, autocompleteComponent: AutocompleteComponent, validator } = props;
const autocompleteRef = useRef<HTMLDivElement>(null);
const inputRef = useRef<HTMLInputElement>(null);
const classes = useStyles();
const router = useRouter();
const dispatch = useDispatch();
const [currentIdx, setCurrentIdx] = useState(-1);
const [state, { handleInputBlur, handleInputChange, handleInputFocus }] = useField({
inputValidator: validator,
});
const { isFocused, isValid, value } = state;
const [list, { hasError }] = useAutocomplete<AutocompleteResponse['data']>(value, async (query: string) =>
searchApi.autocomplete[type](query).then((res) => (res.data as unknown) as AutocompleteResponse['data']),
);
const handleSelect = (alias: string): void => {
handleInputChange(alias);
onChange(alias, type);
handleInputBlur();
};
const handleFocus = (): void => {
handleInputFocus();
inputRef.current.focus();
};
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
handleInputChange(event);
const isValueValid = validator ? validator(event.target.value).success : true;
onChange(event.target.value, event.target.name, isValueValid);
};
useClickOutside(autocompleteRef, () => {
handleInputBlur();
});
useEffect(() => {
(async (): Promise<void> => {
if (router.pathname !== '/' && !value) {
const { alias, slug } = await getInitialInputValuesFromQuery(router, type);
handleInputChange(alias);
onChange(alias, type, isValid, slug);
}
})();
}, []);
return (
<div className={classes['search-input']} ref={autocompleteRef}>
<div onClick={handleFocus}>
<label
className={cx(classes['search-input__input__label'], {
[classes['search-input__input__label--active']]: isFocused || !!value,
})}
>
{label}
</label>
<input
id={inputName}
onChange={handleChange}
onFocus={handleInputFocus}
name={inputName}
value={value}
className={classes['search-input__input__field']}
autoComplete="off"
checked={false}
ref={inputRef}
maxLength={25}
/>
<div
className={cx(classes['input__decorator'], {
[classes['input__decorator--focused']]: isFocused,
})}
/>
</div>
{transitions(
({ transform, opacity }, item) =>
item && (
<animated.div className={classes['search-input__dropdown']} style={{ opacity: opacity as any, transform }}>
{value.length > 2 && (
<AutocompleteComponent
onSelect={handleSelect}
inputValue={value}
currentIndex={currentIdx}
hasError={hasError}
list={list}
/>
)}
</animated.div>
),
)}
</div>
);
};
export default SearchInput;
【问题讨论】:
标签: javascript reactjs typescript