0

I would like to get the text entered in the below input textarea created dynamically after the selection of persons from the dropdown boxes. Would like to get output into a json format: Now it is getting value from the last displayed text area. Could someone please advise ? Provide sample codesandbox link below

Expected output:

[ 
{name:"Bader", reason:"Good news, please add the some data"},
{name:"Crots", reason:"Great person"},
{name:"Dan", reason:"Simple look"}
]

App.js

import React, { useRef, useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { Link, useHistory } from "react-router-dom";
import Multiselect from "multiselect-react-dropdown";

const options = [
  { key: "Aaron", id: 1 },
  { key: "Bader", id: 2 },
  { key: "Crots", id: 3 },
  { key: "Dan", id: 4 },
  { key: "Elep", id: 5 },
  { key: "Pal", id: 6 },
  { key: "Quilt", id: 7 }
];

const App = () => {
  const maxOptions = 3;
  const [selectedOption, setSelectedOption] = useState([]);
  const [nomRegister, setNomRegister] = useState([]);
  const {
    register,
    handleSubmit,
    watch,
    formState: { errors }
  } = useForm();

     
  const handleTypeSelect = (e) => {
    const copy = [...selectedOption];
    copy.push(e);
    setSelectedOption(copy);
  };

  const handleTypeRemove = (e) => {
    const copy = [...selectedOption];
    let index = copy.indexOf(e);
    copy.splice(index, 1);
    setSelectedOption(copy);
  };

  const sendNomination = () => {
    console.log("Doesn't print all, what the heck: " + nomRegister);
  };

  return (
    <div className="App">
      <h1>Person selection</h1>
      <div className="nomineeSelectBox">
        <div id="dialog2" className="triangle_down1"></div>
        <div className="arrowdown">
          <Multiselect
            onSelect={handleTypeSelect}
            onRemove={handleTypeRemove}
            options={selectedOption.length + 1 === maxOptions ? [] : options}
            displayValue="key"
            showCheckbox={true}
            emptyRecordMsg={"Maximum nominees selected !"}
          />
        </div>
      </div>
      <form onSubmit={handleSubmit(sendNomination)}>
        <div className="nomineesSelectedList">
          <h3>Selected Persons</h3>
          {selectedOption.map((x, i) => (
            <div key={i}>
              <div className="row eachrecord">
                <div className="column">
                  <label className="nomlabel">
                    {x[i].key} <b>>></b>
                  </label>
                </div>
                <input
                  required
                  type="textarea"
                  key={i}
                  id={i}
                  name={x[i].key}
                  className="nomineechoosed"
                  onChange={(e) => setNomRegister(e.target.value)}
                />
              </div>
            </div>
          ))}
          <div className="row">
            <div className="buttongroup">
              <input id="Submit" type="submit" value="Submit" />
              <input id="Cancel" type="button" value="Cancel" />
            </div>
          </div>
        </div>
      </form>
    </div>
  );
};

export default App;

Codesandbox link:

https://codesandbox.io/s/elastic-elbakyan-uqpzy?file=/src/App.js

soccerway
  • 10,371
  • 19
  • 67
  • 132

1 Answers1

2

After few modifications, I got a solution.

import React, { useRef, useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { Link, useHistory } from "react-router-dom";
import Multiselect from "multiselect-react-dropdown";

const options = [
  { key: "Aaron", id: 1 },
  { key: "Bader", id: 2 },
  { key: "Crots", id: 3 },
  { key: "Dan", id: 4 },
  { key: "Elep", id: 5 },
  { key: "Pal", id: 6 },
  { key: "Quilt", id: 7 }
];

const App = () => {
  const maxOptions = 3;
  const [selectedOption, setSelectedOption] = useState([]);
  const [nomRegister, setNomRegister] = useState([{}]);
  const {
    register,
    handleSubmit,
    watch,
    formState: { errors }
  } = useForm();

  // const onChange = (e) =>{
  //     e.persist();
  //     setNomRegister({ ...nomRegister, [e.target.id]: e.target.value });
  // }

  const handleTypeSelect = (e) => {
    const copy = [...selectedOption];
    copy.push(e);
    setSelectedOption(copy);
  };

  const handleTypeRemove = (e) => {
    const copy = [...selectedOption];
    console.log(copy);
    let index = copy.indexOf(e);
    copy.splice(index, 1);
    setSelectedOption(copy);
    // immutating state (best practice)
    const updateList = nomRegister.map((item) => {
      return { ...item };
    });
    //delete the specific array case depends on the id
    updateList.splice(index, 1);
    setNomRegister(updateList);
  };

  const sendNomination = () => {
    console.log(
      "Doesn't print all, what the heck: " + JSON.stringify(nomRegister) // i did JSON.stringify just to see the console
    );
  };
  const handleChange = (e, i) => {
    const { name, value } = e.target;
    // immutating state (best practice)
    const updateList = nomRegister.map((item) => {
      return { ...item };
    });
    //change the specific array case depends on the id
    updateList[i] = { ...updateList[i], name: name, reason: value };
    setNomRegister(updateList);
  };
  return (
    <div className="App">
      <h1>Person selection</h1>
      <div className="nomineeSelectBox">
        <div id="dialog2" className="triangle_down1"></div>
        <div className="arrowdown">
          <Multiselect
            onSelect={handleTypeSelect}
            onRemove={handleTypeRemove}
            options={selectedOption.length + 1 === maxOptions ? [] : options}
            displayValue="key"
            showCheckbox={true}
            emptyRecordMsg={"Maximum nominees selected !"}
          />
        </div>
      </div>
      <form onSubmit={handleSubmit(sendNomination)}>
        <div className="nomineesSelectedList">
          <h3>Selected Persons</h3>
          {selectedOption.map((x, i) => (
            <div key={i}>
              <div className="row eachrecord">
                <div className="column">
                  <label className="nomlabel">
                    {x[i].key} <b>>></b>
                  </label>
                </div>
                <input
                  required
                  type="textarea"
                  key={i}
                  id={i}
                  name={x[i].key}
                  className="nomineechoosed"
                  onChange={(e) => handleChange(e, i)}
                />
              </div>
            </div>
          ))}
          <div className="row">
            <div className="buttongroup">
              <input id="Submit" type="submit" value="Submit" />
              <input id="Cancel" type="button" value="Cancel" />
            </div>
          </div>
        </div>
      </form>
    </div>
  );
};

export default App;

check Codesandbox

Ala Hamadi
  • 251
  • 2
  • 7
  • Appreciate you help ! this what I was looking for. Upvoted and accepted – soccerway Aug 10 '21 at 12:23
  • One issue noted, if we added 3 persons with some text entered on clcik on submit displays 3 records in json format which is fine. But while removing any one of the selected option from drop down and them try to submit, it console.log incorrect data – soccerway Aug 10 '21 at 13:00
  • did you copy all my code? because i tried to solve this problem on `handleTypeRemove` – Ala Hamadi Aug 10 '21 at 15:04
  • Yes, I have copied all of that ., – soccerway Aug 10 '21 at 20:49
  • Any idea how can we achieve this >>https://stackoverflow.com/questions/68727633/in-a-react-multiselect-dropdown-i-would-like-to-display-name-and-email-along-wit – soccerway Aug 11 '21 at 01:40