У меня есть компонент реакции-выбора (который создается с помощью CreatableSelect), это ввод текста с множественным выбором, который позволяет пользователям добавлять ключевые слова в качестве параметров.
Он работает нормально, но мне нужен способ, позволяющий пользователям копировать текст, разделенный запятыми, и вставлять его в компонент, чтобы каждый элемент добавлялся как отдельная опция.
Например, если текст «123 456 789», ожидаемый результат будет 3 отдельных варианта: 123, 456 и 789 соответственно.
Вот мой компонент
import React, {KeyboardEventHandler} from 'react';
import CreatableSelect from 'react-select/creatable';
import { ActionMeta, OnChangeValue } from 'react-select';
const MultiSelectTextInput = (props) => {
const components = {
DropdownIndicator: null,
};
interface Option {
readonly label: string;
readonly value: string;
}
const createOption = (label: string) => ({
label,
value: label,
});
const handleChangeEvent = (value: OnChangeValue<Option, true>, actionMeta: ActionMeta<Option>) => {
console.group('Value Changed');
console.info(value);
console.info(`action: ${actionMeta.action}`);
console.groupEnd();
props.setValue(value);
};
const handleInputChange = (inputValue: string) => {
props.setInputValue(inputValue);
};
const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = (event) => {
if (!props.inputValue) return;
switch (event.key) {
case 'Enter':
case 'Tab':
if (props.value.map(v => v.label).includes(props.inputValue)) {
console.info('Value Already Exists!')
props.setInputValue('');
}
else {
console.group('Value Added');
console.info(props.value);
console.groupEnd();
props.setInputValue('');
props.setValue([...props.value, createOption(props.inputValue)])
}
event.preventDefault();
}
};
return (
<CreatableSelect
id = {props.id}
instanceId = {props.id}
className = "w-100"
components = {components}
inputValue = {props.inputValue}
isClearable
isMulti
menuIsOpen = {false}
onChange = {handleChangeEvent}
onInputChange = {handleInputChange}
onKeyDown = {handleKeyDown}
placeholder = {props.placeholder}
value = {props.value}
/>
);
};
export default MultiSelectTextInput;
Я вызываю этот компонент со страницы (проекта next.js), как показано ниже. Компонент изменяет состояние страницы, на которой он вызывается.
...
import MultiSelectTextInput from "../components/Form/MultiSelect/MultiSelectTextInput";
...
const NcciLite = () => {
const [value, setValue] = useState<any>([]);
const [inputValue, setInputValue] = useState<any>('');
...
return (
<React.Fragment>
<Container fluid = {true}>
<Breadcrumbs title = "Tools" breadcrumbItem = "NCCI Lite" />
<Row>
<Col>
<Card>
<CardBody>
<CardTitle className = "mb-4 fw-light">...</CardTitle>
<Form onSubmit = {event => event.preventDefault()}>
...
<Row className = "mb-4">
<Col>
<div className = "d-inline-flex col-md-9">
<MultiSelectTextInput
id = "codes"
value = {value}
setValue = {setValue}
inputValue = {inputValue}
setInputValue = {setInputValue}
placeholder = "Type Next Code(s) or Paste Here"
/>
</div>
</Col>
</Row>
...
</Form>
</CardBody>
</Card>
</Col>
</Row>
</Container>
</React.Fragment>
};
export default NcciLite;
Любая помощь будет оценена
Хорошо, я отвечу на свой вопрос. Я думал, что это будет сложно, но на самом деле это не так. Всего несколько строк кода JavaScript.
Модифицированный компонент
import React, {KeyboardEventHandler} from 'react';
import CreatableSelect from 'react-select/creatable';
import { ActionMeta, OnChangeValue } from 'react-select';
const MultiSelectTextInput = (props) => {
const components = {
DropdownIndicator: null,
};
interface Option {
readonly label: string;
readonly value: string;
}
const createOption = (label: string) => ({
label,
value: label,
});
const handleChangeEvent = (value: OnChangeValue<Option, true>, actionMeta: ActionMeta<Option>) => {
// console.group('Value Changed');
// console.info(value);
// console.info(`action: ${actionMeta.action}`);
// console.groupEnd();
props.setValue(value);
};
const handleInputChange = (inputValue: string) => {
props.setInputValue(inputValue);
};
const handleKeyDown: KeyboardEventHandler<HTMLDivElement> = (event) => {
if (!props.inputValue) return;
switch (event.key) {
case 'Enter':
case 'Tab':
if (props.value.map(v => v.label.trim()).includes(props.inputValue.trim())) {
// console.info('Value Already Exists!')
props.setInputValue('');
}
else {
// console.group('Value Added');
// console.info(props.value);
// console.groupEnd();
if (!props.customizedSetter && props.inputValue.trim().indexOf(',') > -1) {
props.setInputValue('');
const values = props.inputValue.trim().split(',').filter(iv => !props.value.map(v => v.label.trim()).includes(iv.trim()));
for (let i = 0; i < values.length; i++) {
props.setValue((oldValue) =>[...oldValue, createOption(values[i].trim())]);
}
}
else {
props.setInputValue('');
props.setValue([...props.value, createOption(props.inputValue.trim())]);
}
}
event.preventDefault();
}
};
return (
<CreatableSelect
id = {props.id}
instanceId = {props.id}
className = "cs w-100"
components = {components}
inputValue = {props.inputValue}
isClearable
isMulti
menuIsOpen = {false}
onChange = {handleChangeEvent}
onInputChange = {handleInputChange}
onKeyDown = {handleKeyDown}
placeholder = {props.placeholder}
value = {props.value}
/>
);
};
export default MultiSelectTextInput;