复杂的选择和输入文本字段组合,具有添加更多和删除选项。

huangapple go评论76阅读模式
英文:

Complex Select and Input Text Filed Combo with add more and remove option

问题

我有一个下拉框,还有一个文本字段。用户可以选择他们提供的链接类型,然后在输入文本中提供链接。此外,他们可以添加不同类型的更多链接。每种类型只能有一个链接。如果他们犯了错误,他们可以移除任何链接。

我陷入了这个问题,无法找到任何简单的解决方案。

所需的最终输出是一个数组 projectLinks。[{web:"url"},{android:"url"}]

请帮忙。

复杂的选择和输入文本字段组合,具有添加更多和删除选项。
React 代码:

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.

复杂的选择和输入文本字段组合,具有添加更多和删除选项。
React Code:

import MainLayout from &quot;./layouts/MainLayout&quot;;
const linkOptions = [
{ value: &quot;web&quot;, label: &quot;Web&quot; },
{ value: &quot;android&quot;, label: &quot;Android&quot; },
{ value: &quot;ios&quot;, label: &quot;iOS&quot; },
{ value: &quot;youtube&quot;, label: &quot;Youtube&quot; },
{ value: &quot;twitter&quot;, label: &quot;Twitter&quot; }
];
type ProjectLinks = [
{ web?: string },
{ android?: string },
{ ios?: string },
{ youtube?: string },
{ twitter?: string }
];
export default function App() {
const [projectLinks, setProjectLinks] = useState&lt;ProjectLinks&gt;();
const [numberOfLinks, setNumberOfLinks] = useState(1);
const handleChangeOption = (event: any) =&gt; {
console.log(event.target.value);
};
const submit = () =&gt; {
console.log(&quot;Submitted&quot;);
};
const handleAddLink = () =&gt; {
setNumberOfLinks((prev) =&gt; prev + 1);
};
const handleRemoveLink = () =&gt; {
setNumberOfLinks((prev) =&gt; prev - 1);
};
return (
&lt;MainLayout&gt;
&lt;div className=&quot;flex flex-col&quot;&gt;
{[...Array(numberOfLinks)].map((_, index) =&gt; (
&lt;LinkField
key={index}
handleChangeOption={handleChangeOption}
handleAddLink={handleAddLink}
handleRemoveLink={handleRemoveLink}
/&gt;
))}
&lt;button className=&quot;btn btn-active mt-8&quot; onClick={submit}&gt;
Button
&lt;/button&gt;
&lt;/div&gt;
&lt;/MainLayout&gt;
);
}
function LinkField({
handleChangeOption,
handleAddLink,
handleRemoveLink
}: {
handleChangeOption: (event: any) =&gt; void;
handleAddLink: () =&gt; void;
handleRemoveLink: () =&gt; void;
}) {
return (
&lt;div className=&quot;mt-1 mb-1&quot;&gt;
&lt;div className=&quot;flex justify-between&quot;&gt;
&lt;select onChange={handleChangeOption} className=&quot;select select-primary&quot;&gt;
{linkOptions.map((option, index) =&gt; (
&lt;option key={index} value={option.value}&gt;
{option.label}
&lt;/option&gt;
))}
&lt;/select&gt;
&lt;input
type=&quot;text&quot;
placeholder=&quot;example.com&quot;
className=&quot;input input-bordered ml-1 mr-1&quot;
/&gt;
&lt;button
className=&quot;btn btn-md btn-active ml-1 mr-1&quot;
onClick={handleAddLink}
&gt;
Add
&lt;/button&gt;
&lt;button
className=&quot;btn btn-md btn-active ml-1 mr-1&quot;
onClick={handleRemoveLink}
&gt;
Remove
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
);
}

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 &quot;react&quot;;
import MainLayout from &quot;./layouts/MainLayout&quot;;
const linkOptions = [
{ value: &quot;web&quot;, label: &quot;Web&quot; },
{ value: &quot;android&quot;, label: &quot;Android&quot; },
{ value: &quot;ios&quot;, label: &quot;iOS&quot; },
{ value: &quot;youtube&quot;, label: &quot;Youtube&quot; },
{ value: &quot;twitter&quot;, label: &quot;Twitter&quot; }
];
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) =&gt; {
let urlTypeArray: string[] = [];
let urlArray: string[] = [];
let projectLinks: ProjectLinks[] = [];
[...Array(count)].map((_, index) =&gt; {
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 &amp;&amp; projectLinks.length) {
console.log(projectLinks);
// Action for URL submit to API
}
event.preventDefault();
};
const handleAddLink = () =&gt; {
setCount((prev) =&gt; (prev &lt; linkOptions.length ? prev + 1 : prev));
};
const handleRemoveLink = () =&gt; {
setCount((prev) =&gt; (prev &gt; 1 ? prev - 1 : prev));
};
return (
&lt;MainLayout&gt;
&lt;form className=&quot;flex flex-col&quot; onSubmit={submit}&gt;
{[...Array(count)].map((link, index) =&gt; (
&lt;LinkField
key={index}
index={index}
handleAddLink={handleAddLink}
handleRemoveLink={handleRemoveLink}
/&gt;
))}
&lt;button
className={`btn ${urlError ? &quot;btn-disabled&quot; : &quot;btn-active&quot;} mt-8`}
&gt;
Button
&lt;/button&gt;
{urlError ? (
&lt;div
className=&quot;toast cursor-pointer&quot;
onClick={() =&gt; setUrlError(false)}
&gt;
&lt;div className=&quot;alert alert-error&quot;&gt;
&lt;span&gt;Duplicate URL Type or URL or URL is Empty.&lt;/span&gt;
&lt;/div&gt;
&lt;/div&gt;
) : null}
&lt;/form&gt;
&lt;/MainLayout&gt;
);
}
function LinkField({
handleAddLink,
handleRemoveLink,
index
}: {
handleAddLink: () =&gt; void;
handleRemoveLink: () =&gt; void;
index: number;
}) {
return (
&lt;div className=&quot;mt-1 mb-1&quot;&gt;
&lt;div className=&quot;flex justify-between&quot;&gt;
&lt;select name=&quot;urlType&quot; className=&quot;select select-primary&quot;&gt;
{linkOptions.map((option, index) =&gt; (
&lt;option key={index} value={option.value}&gt;
{option.label}
&lt;/option&gt;
))}
&lt;/select&gt;
&lt;input
type=&quot;text&quot;
name=&quot;url&quot;
placeholder=&quot;example.com&quot;
className=&quot;input input-bordered ml-1 mr-1&quot;
/&gt;
&lt;button
className={`btn ${
index === linkOptions.length - 1 ? &quot;btn-disabled&quot; : &quot;&quot;
} ml-1 mr-1`}
onClick={handleAddLink}
type=&quot;button&quot;
&gt;
Add
&lt;/button&gt;
&lt;button
className={`btn ${index === 0 ? &quot;btn-disabled&quot; : &quot;&quot;} ml-1 mr-1`}
onClick={handleRemoveLink}
// type=&quot;button&quot;
&gt;
Remove
&lt;/button&gt;
&lt;/div&gt;
&lt;/div&gt;
);
}

huangapple
  • 本文由 发表于 2023年6月1日 15:46:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/76379701.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定