英文:
Complex Select and Input Text Filed Combo with add more and remove option
问题
我有一个下拉框,还有一个文本字段。用户可以选择他们提供的链接类型,然后在输入文本中提供链接。此外,他们可以添加不同类型的更多链接。每种类型只能有一个链接。如果他们犯了错误,他们可以移除任何链接。
我陷入了这个问题,无法找到任何简单的解决方案。
所需的最终输出是一个数组 projectLinks。[{web:"url"},{android:"url"}]
请帮忙。
import { useState } from "react";
import MainLayout from "./layouts/MainLayout";
const linkOptions = [
{ value: "web", label: "Web" },
{ value: "android", label: "Android" },
{ value: "ios", label: "iOS" },
{ value: "youtube", label: "Youtube" },
{ value: "twitter", label: "Twitter" }
];
type ProjectLinks = [
{ web?: string },
{ android?: string },
{ ios?: string },
{ youtube?: string },
{ twitter?: string }
];
export default function App() {
const [projectLinks, setProjectLinks] = useState<ProjectLinks>();
const [numberOfLinks, setNumberOfLinks] = useState(1);
const handleChangeOption = (event: any) => {
console.log(event.target.value);
};
const submit = () => {
console.log("已提交");
};
const handleAddLink = () => {
setNumberOfLinks((prev) => prev + 1);
};
const handleRemoveLink = () => {
setNumberOfLinks((prev) => prev - 1);
};
return (
<MainLayout>
<div className="flex flex-col">
{[...Array(numberOfLinks)].map((_, index) => (
<LinkField
key={index}
handleChangeOption={handleChangeOption}
handleAddLink={handleAddLink}
handleRemoveLink={handleRemoveLink}
/>
))}
<button className="btn btn-active mt-8" onClick={submit}>
按钮
</button>
</div>
</MainLayout>
);
}
function LinkField({
handleChangeOption,
handleAddLink,
handleRemoveLink
}: {
handleChangeOption: (event: any) => void;
handleAddLink: () => void;
handleRemoveLink: () => void;
}) {
return (
<div className="mt-1 mb-1">
<div className="flex justify-between">
<select onChange={handleChangeOption} className="select select-primary">
{linkOptions.map((option, index) => (
<option key={index} value={option.value}>
{option.label}
</option>
))}
</select>
<input
type="text"
placeholder="example.com"
className="input input-bordered ml-1 mr-1"
/>
<button
className="btn btn-md btn-active ml-1 mr-1"
onClick={handleAddLink}
>
添加
</button>
<button
className="btn btn-md btn-active ml-1 mr-1"
onClick={handleRemoveLink}
>
移除
</button>
</div>
</div>
);
}
我正在使用 tailwindcss 和 daisyui。
英文:
I have a drop down also a text filed. User can select which kind of link they are providing and then give link in input text.
Also they can add more links of different kind. Only 1 link of 1 kind.
If they made mistake they can remove any link.
I am stuck in this problem and unable to figure out any simple solution.
Final output required is an array projectLinks. [{web:"url"},{android:"url"}]
Please help.
import MainLayout from "./layouts/MainLayout";
const linkOptions = [
{ value: "web", label: "Web" },
{ value: "android", label: "Android" },
{ value: "ios", label: "iOS" },
{ value: "youtube", label: "Youtube" },
{ value: "twitter", label: "Twitter" }
];
type ProjectLinks = [
{ web?: string },
{ android?: string },
{ ios?: string },
{ youtube?: string },
{ twitter?: string }
];
export default function App() {
const [projectLinks, setProjectLinks] = useState<ProjectLinks>();
const [numberOfLinks, setNumberOfLinks] = useState(1);
const handleChangeOption = (event: any) => {
console.log(event.target.value);
};
const submit = () => {
console.log("Submitted");
};
const handleAddLink = () => {
setNumberOfLinks((prev) => prev + 1);
};
const handleRemoveLink = () => {
setNumberOfLinks((prev) => prev - 1);
};
return (
<MainLayout>
<div className="flex flex-col">
{[...Array(numberOfLinks)].map((_, index) => (
<LinkField
key={index}
handleChangeOption={handleChangeOption}
handleAddLink={handleAddLink}
handleRemoveLink={handleRemoveLink}
/>
))}
<button className="btn btn-active mt-8" onClick={submit}>
Button
</button>
</div>
</MainLayout>
);
}
function LinkField({
handleChangeOption,
handleAddLink,
handleRemoveLink
}: {
handleChangeOption: (event: any) => void;
handleAddLink: () => void;
handleRemoveLink: () => void;
}) {
return (
<div className="mt-1 mb-1">
<div className="flex justify-between">
<select onChange={handleChangeOption} className="select select-primary">
{linkOptions.map((option, index) => (
<option key={index} value={option.value}>
{option.label}
</option>
))}
</select>
<input
type="text"
placeholder="example.com"
className="input input-bordered ml-1 mr-1"
/>
<button
className="btn btn-md btn-active ml-1 mr-1"
onClick={handleAddLink}
>
Add
</button>
<button
className="btn btn-md btn-active ml-1 mr-1"
onClick={handleRemoveLink}
>
Remove
</button>
</div>
</div>
);
}
I am using tailwindcss with daisyui.
答案1
得分: 1
我通过避免大部分状态变量并使用表单提交来解决了这个问题。
import { useState } from "react";
import MainLayout from "./layouts/MainLayout";
const linkOptions = [
{ value: "web", label: "Web" },
{ value: "android", label: "Android" },
{ value: "ios", label: "iOS" },
{ value: "youtube", label: "Youtube" },
{ value: "twitter", label: "Twitter" }
];
type ProjectLinks = [
{ web?: string },
{ android?: string },
{ ios?: string },
{ youtube?: string },
{ twitter?: string }
];
export default function App() {
const [count, setCount] = useState(1);
const [urlError, setUrlError] = useState(false);
const submit = (event: any) => {
let urlTypeArray: string[] = [];
let urlArray: string[] = [];
let projectLinks: ProjectLinks[] = [];
[...Array(count)].map((_, index) => {
let url =
count === 1 ? event.target.url.value : event.target.url[index].value;
let urlType =
count === 1
? event.target.urlType.value
: event.target.urlType[index].value;
if (
urlTypeArray.includes(urlType) ||
urlArray.includes(url) ||
!url.length
) {
setUrlError(true);
return null;
} else {
urlTypeArray.push(urlType);
urlArray.push(url);
var urlObj: any = {};
urlObj[urlType] = url;
projectLinks = [...projectLinks, urlObj];
}
});
if (!urlError && projectLinks.length) {
console.log(projectLinks);
// 提交到API的URL操作
}
event.preventDefault();
};
const handleAddLink = () => {
setCount((prev) => (prev < linkOptions.length ? prev + 1 : prev));
};
const handleRemoveLink = () => {
setCount((prev) => (prev > 1 ? prev - 1 : prev));
};
return (
<MainLayout>
<form className="flex flex-col" onSubmit={submit}>
{[...Array(count)].map((link, index) => (
<LinkField
key={index}
index={index}
handleAddLink={handleAddLink}
handleRemoveLink={handleRemoveLink}
/>
))}
<button
className={`btn ${urlError ? "btn-disabled" : "btn-active"} mt-8`}
>
Button
</button>
{urlError ? (
<div
className="toast cursor-pointer"
onClick={() => setUrlError(false)}
>
<div className="alert alert-error">
<span>Duplicate URL Type or URL or URL is Empty.</span>
</div>
</div>
) : null}
</form>
</MainLayout>
);
}
function LinkField({
handleAddLink,
handleRemoveLink,
index
}: {
handleAddLink: () => void;
handleRemoveLink: () => void;
index: number;
}) {
return (
<div className="mt-1 mb-1">
<div className="flex justify-between">
<select name="urlType" className="select select-primary">
{linkOptions.map((option, index) => (
<option key={index} value={option.value}>
{option.label}
</option>
))}
</select>
<input
type="text"
name="url"
placeholder="example.com"
className="input input-bordered ml-1 mr-1"
/>
<button
className={`btn ${
index === linkOptions.length - 1 ? "btn-disabled" : ""
} ml-1 mr-1`}
onClick={handleAddLink}
type="button"
>
Add
</button>
<button
className={`btn ${index === 0 ? "btn-disabled" : ""} ml-1 mr-1`}
onClick={handleRemoveLink}
// type="button"
>
Remove
</button>
</div>
</div>
);
}
英文:
I solved it by avoiding most of the state variables and used form submit.
import { useState } from "react";
import MainLayout from "./layouts/MainLayout";
const linkOptions = [
{ value: "web", label: "Web" },
{ value: "android", label: "Android" },
{ value: "ios", label: "iOS" },
{ value: "youtube", label: "Youtube" },
{ value: "twitter", label: "Twitter" }
];
type ProjectLinks = [
{ web?: string },
{ android?: string },
{ ios?: string },
{ youtube?: string },
{ twitter?: string }
];
export default function App() {
const [count, setCount] = useState(1);
const [urlError, setUrlError] = useState(false);
const submit = (event: any) => {
let urlTypeArray: string[] = [];
let urlArray: string[] = [];
let projectLinks: ProjectLinks[] = [];
[...Array(count)].map((_, index) => {
let url =
count === 1 ? event.target.url.value : event.target.url[index].value;
let urlType =
count === 1
? event.target.urlType.value
: event.target.urlType[index].value;
if (
urlTypeArray.includes(urlType) ||
urlArray.includes(url) ||
!url.length
) {
setUrlError(true);
return null;
} else {
urlTypeArray.push(urlType);
urlArray.push(url);
var urlObj: any = {};
urlObj[urlType] = url;
projectLinks = [...projectLinks, urlObj];
}
});
if (!urlError && projectLinks.length) {
console.log(projectLinks);
// Action for URL submit to API
}
event.preventDefault();
};
const handleAddLink = () => {
setCount((prev) => (prev < linkOptions.length ? prev + 1 : prev));
};
const handleRemoveLink = () => {
setCount((prev) => (prev > 1 ? prev - 1 : prev));
};
return (
<MainLayout>
<form className="flex flex-col" onSubmit={submit}>
{[...Array(count)].map((link, index) => (
<LinkField
key={index}
index={index}
handleAddLink={handleAddLink}
handleRemoveLink={handleRemoveLink}
/>
))}
<button
className={`btn ${urlError ? "btn-disabled" : "btn-active"} mt-8`}
>
Button
</button>
{urlError ? (
<div
className="toast cursor-pointer"
onClick={() => setUrlError(false)}
>
<div className="alert alert-error">
<span>Duplicate URL Type or URL or URL is Empty.</span>
</div>
</div>
) : null}
</form>
</MainLayout>
);
}
function LinkField({
handleAddLink,
handleRemoveLink,
index
}: {
handleAddLink: () => void;
handleRemoveLink: () => void;
index: number;
}) {
return (
<div className="mt-1 mb-1">
<div className="flex justify-between">
<select name="urlType" className="select select-primary">
{linkOptions.map((option, index) => (
<option key={index} value={option.value}>
{option.label}
</option>
))}
</select>
<input
type="text"
name="url"
placeholder="example.com"
className="input input-bordered ml-1 mr-1"
/>
<button
className={`btn ${
index === linkOptions.length - 1 ? "btn-disabled" : ""
} ml-1 mr-1`}
onClick={handleAddLink}
type="button"
>
Add
</button>
<button
className={`btn ${index === 0 ? "btn-disabled" : ""} ml-1 mr-1`}
onClick={handleRemoveLink}
// type="button"
>
Remove
</button>
</div>
</div>
);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论