nathan
nathan

Reputation: 369

How to create dynamic add input field

I am trying to create a dynamic add input field when user type insde the input the add button will available to click on. And after click on add it will appear another input field.

Here is how the it look like:

enter image description here

and here is what I have implemented:

  const [inputs, setInputs] = useState(
    teamData.rules.map((value) => ({
      value,
      guid: uuidV4(),
    }))
  );

  const addInputs = (event) => {
    event.preventDefault();
    setInputs((inputs) => [
      ...inputs,
      {
        name: `rule_${inputs.length + 1}`,
        guid: uuidV4(),
      },
    ]);
  };
  const removeInputs = (index) => {
    const newList = inputs.filter((item, i) => index !== i);
    setInputs(newList);
  };
  const clearInput = (dataName) => {
    setUpdateTeamData((prevState) => {
      delete prevState[dataName];
      return {
        ...prevState,
      };
    });
  };

<div>
  {inputs?.map((data, idx) => {
    return (
      <div className="agreement-form-grid" key={data.guid}>
        <button
          type="button"
          className="agreement-remove-button"
          onClick={() => {
            removeInputs(idx);
            clearInput(`rule_${idx}`);
          }}
        >
          <Remove />
        </button>
        <input
          name={`rule_${idx}`}
          onChange={handleChange}
          placeholder={`Rule ${idx + 1}`}
          defaultValue={teamData.rules[idx]}
        />
      </div>
    );
  })}

enter image description here

How can I achieve the feature like the first picture?

Upvotes: 0

Views: 42

Answers (1)

alisasani
alisasani

Reputation: 2968

you need two variable. One is an array storing the list of added rules, and the second one is the string for keeping the value of the rule that is not yet added to the array:

const [rules, setRules] = useState([{ value: "test", id: 0 }]);
  const [preAddedRule, setPreAddedRule] = useState("");

Then, by relying on these functions you can add and remove rules to your variables:

const handleRemove = (id) => {
    setRules(rules.filter((rule, i) => rule.id !== id));
  };
  const handleAdd = (id) => {
    setRules([...rules, { value: preAddedRule, id: rules.length }]);
    setPreAddedRule("");
  };
  const handleChange = (e) => {
    setPreAddedRule(e.target.value);
  };

Just remember to clear the value of the preAddedRule after adding it to array, in order to prepare it for the next rules.

And finally, display all your rules, inputs and buttons as below:

{rules.map((el, i) => (
        <div>
          <input value={el.value} />
          <button onClick={() => handleRemove(el.id)}>delete</button>
        </div>
      ))}
      <input onChange={handleChange} value={preAddedRule} />
      <button onClick={() => handleAdd()}>Add</button>

sandbox

Upvotes: 1

Related Questions