Home > other >  How to change a html tag, inside a map function, if a specific condition is met
How to change a html tag, inside a map function, if a specific condition is met

Time:03-16

So i have an array that is mapped and displaying multiple table rows. And each of them also has a button that can be clicked. So i want to make it so, that whenever the button is clicked, it changes from displaying data ( tags) to input tags. So i can edit that data. My problem is that, whenever the button is clicked, it changes not only one table row, but all the table rows. I know it's because of the map function, but i don't really know how to fix that. I thought doing something similar to handleRowRemove function, but i really can't seem to figure out how to do that.

import { useState } from "react";

const Pricing = ({ register, errors }) => {
  const [tableRows, setTableRows] = useState([
    { price: 12, description: "E", deliveryTime: "10 work days" },
  ]);
  const [edit, setEdit] = useState(false);

  const [rowValues, setRowValues] = useState({
    price: 5,
    description: "",
    deliveryTime: "",
  });

  const handleRowRemove = (itemToRemove) => {
    setTableRows(tableRows.filter((item) => item !== itemToRemove));
  };

  const handelRowAdd = () => {
    setTableRows([...tableRows, { ...rowValues }]);
    console.log(tableRows);
  };

  const handleEdit = (i, index) => {
    //
  };

  return (
    <section>
      <table className="table w-full text-white ">
        <thead className="">
          <tr>
            <th>Price</th>
            <th>Description</th>
            <th>Delivery time</th>
            <th>Edit/Delete</th>
          </tr>
        </thead>
        <tbody>
          {tableRows.map((i) => (
            <tr>
              {edit ? (
                <>
                  <td>IN EDIT MODE</td>
                  <td>IN EDIT MODE</td>
                  <td>IN EDIT MODE</td>
                </>
              ) : (
                <>
                  <td>{i.price}</td>
                  <td>{i.description}</td>
                  <td>{i.deliveryTime}</td>
                </>
              )}

              <td>
                <div className="flex">
                  {edit ? (
                    <button type="button" onClick={() => setEdit(false)}>
                      <svg
                        xmlns="http://www.w3.org/2000/svg"
                        className="h-6 w-6"
                        fill="none"
                        viewBox="0 0 24 24"
                        stroke="currentColor"
                        strokeWidth={2}
                      >
                        <path
                          strokeLinecap="round"
                          strokeLinejoin="round"
                          d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"
                        />
                      </svg>
                    </button>
                  ) : (
                    <>
                      <button
                        className="pr-4 tooltip"
                        data-tip="Edit"
                        onClick={() => setEdit(true)}
                        type="button"
                      >
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          className="h-6 w-6"
                          fill="none"
                          viewBox="0 0 24 24"
                          stroke="currentColor"
                          strokeWidth={2}
                        >
                          <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"
                          />
                        </svg>
                      </button>
                      <button
                        className="tooltip"
                        data-tip="Remove"
                        onClick={() => handleRowRemove(i)}
                        type="button"
                      >
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          className="h-6 w-6"
                          fill="none"
                          viewBox="0 0 24 24"
                          stroke="currentColor"
                          strokeWidth={2}
                        >
                          <path
                            strokeLinecap="round"
                            strokeLinejoin="round"
                            d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"
                          />
                        </svg>
                      </button>
                    </>
                  )}
                </div>
              </td>
            </tr>
          ))}

          <tr>
            <td>
              <input
                type="text"
                className="input bg-indigo-500 focus:bg-indigo-500 placeholder-gray-200"
                placeholder="Price"
                value={rowValues.price}
                onChange={(e) =>
                  setRowValues({ ...rowValues, price: e.target.value })
                }
              />
            </td>
            <td>
              <input
                type="text"
                className="input bg-indigo-500 focus:bg-indigo-500 placeholder-gray-200"
                placeholder="Description"
                value={rowValues.description}
                onChange={(e) =>
                  setRowValues({ ...rowValues, description: e.target.value })
                }
              />
            </td>
            <td>
              <input
                type="text"
                className="input bg-indigo-500 focus:bg-indigo-500 placeholder-gray-200"
                placeholder="Delivery Time"
                value={rowValues.deliveryTime}
                onChange={(e) =>
                  setRowValues({ ...rowValues, deliveryTime: e.target.value })
                }
              />
            </td>
            <td>
              {" "}
              <button onClick={handelRowAdd} type="button">
                <svg
                  xmlns="http://www.w3.org/2000/svg"
                  className="h-10 w-10"
                  fill="none"
                  viewBox="0 0 24 24"
                  stroke="currentColor"
                  strokeWidth={2}
                >
                  <path
                    strokeLinecap="round"
                    strokeLinejoin="round"
                    d="M12 9v3m0 0v3m0-3h3m-3 0H9m12 0a9 9 0 11-18 0 9 9 0 0118 0z"
                  />
                </svg>
              </button>
            </td>
          </tr>
        </tbody>
      </table>
    </section>
  );
};

export default Pricing;

Any help would be appreciated. Thanks.

CodePudding user response:

I would recommend you extract the contents of your map function into a separate functional component and handle the edit flag within that. Along the lines of

const Row = ({ rowData, onEditComplete }) => {
     const [edit, setEdit] = useState(false);
     
     return (
         <tr>
             // ...etc
             <td>{rowData.price}</td>
             // ...etc
         </tr>
     );
}

Then in your Pricing function it becomes

{tableRows.map((i) => (
    <Row 
        rowData={i} 
        onEditComplete={() => {
            //use this to pass edited row data back to the parent
        }
    />
)}

CodePudding user response:

Get the index from the map tableRows.map((i, index) =>

Add a new state to keep track of the edit index.

onClick={() => {setEditIndex(index); 
                setEdit(true)}}

Check if the row is the edit row.

{edit && editIndex === index ? (
                <>
                  <td>IN EDIT MODE</td>
                  <td>IN EDIT MODE</td>
                  <td>IN EDIT MODE</td>
                </>
              ) : (
                <>
                  <td>{i.price}</td>
                  <td>{i.description}</td>
                  <td>{i.deliveryTime}</td>
                </>
              )}
  • Related