英文:
How to design an input field for creating React components?
问题
我正在使用 React 18.2.0。我想设计一个像下面图片中的输入字段,用户可以添加多个芯片,然后保存这些芯片并将它们传递到后端项目。
我在material-UI的<Autocomplete>
标签部分看到过这个组件:
但我不想有任何预定义的选项与选择菜单,只想让用户输入任何他们想要的东西,然后在按Enter键后创建一个新的芯片。
换句话说,我需要一个<TextField>
,允许用户创建多个芯片。
我也尝试过material-ui-chip-input包,但在我点击Enter按钮后,我的页面的其他按钮会被修改,<ChipInput />
不能很好地修改,而且它适用于较旧版本的material-UI。我正在寻找更好的实现方式。
感谢任何帮助。
英文:
I am working with React 18.2.0. I want to design an input field like the below image, in which user can add multiple chips, and then save those chips and pass them to the backend project.
I have seen this component in <Autocomplete>
tag section in material-UI:
But I don't want to have any predefined options with a select menu, and just want to let the users to type any thing that they want, and create a new chip after pressing on Enter button.
In the other words a <TextField>
which let the users to create multiple chips.
I have also tried the material-ui-chip-input package, but after I click on enter button, the other buttons of my page would be modified, and the <ChipInput />
can not be well modified, and it is for older versions of material-UI. And I am searching for a better way to implement something like this.
I will be grateful for any help.
答案1
得分: 1
以下是代码的翻译部分:
你可以创建一个包装的 div,内部放置一个未经样式化的输入元素。为输入字段添加一个监听器,当按下 Enter 键时创建一个新的芯片(chip),然后清空输入。芯片将放置在包装器内的一行,而随着添加更多项目,输入字段将被推向右侧。
const MultiChipInput = () => {
const [items, setItems] = useState([]);
const [inputValue, setInputValue] = useState("");
const addItem = (event) => {
if (event.code === "Enter") {
let _items = [...items];
_items.push(event.target.value);
setItems(_items);
setInputValue("");
}
};
const removeItem = (item) => {
const _items = items.filter((x) => x !== item);
setItems(_items);
};
return (
<div className="wrapper">
{items.map((item) => (
<div className="chip">
{item}
<span onClick={() => removeItem(item)}>x</span>
</div>
))}
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
type="text"
className="myInput"
onKeyDown={addItem}
/>
</div>
);
};
CSS 部分:
.wrapper {
background-color: white;
display: flex;
flex-direction: row;
gap: 4px;
padding: 4px;
border-radius: 4px;
}
.myInput {
all: unset;
}
.chip {
border: 1px solid blue;
border-radius: 5px;
padding: 2px 10px;
}
.chip > span {
margin-left: 4px;
cursor: pointer;
}
结果图像:
英文:
You could create a wrapper div with an unstyled input element inside. Add a listener to your input field which will create a new chip when Enter is pressed, and clear the input. The chips will be placed on a row inside the wrapper, while the input field will be pushet to the right as more and more items are added.
const MultiChipInput = () => {
const [items, setItems] = useState([]);
const [inputValue, setInputValue] = useState("");
const addItem = (event) => {
if (event.code === "Enter") {
let _items = [...items];
_items.push(event.target.value);
setItems(_items);
setInputValue("");
}
};
const removeItem = (item) => {
const _items = items.filter((x) => x !== item);
setItems(_items);
};
return (
<div className="wrapper">
{items.map((item) => (
<div className="chip">
{item}
<span onClick={() => removeItem(item)}>x</span>
</div>
))}
<input
value={inputValue}
onChange={(e) => setInputValue(e.target.value)}
type="text"
className={"myInput"}
onKeyDown={addItem}
/>
</div>
);
};
CSS:
.wrapper {
background-color: white;
display: flex;
flex-direction: row;
gap: 4px;
padding: 4px;
border-radius: 4px;
}
.myInput {
all: unset;
}
.chip {
border: 1px solid blue;
border-radius: 5px;
padding: 2px 10px;
}
.chip > span {
margin-left: 4px;
cursor: pointer;
}
RESULT:
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论