【问题标题】:making fields editable in row in reactjs在reactjs中使字段在行中可编辑
【发布时间】:2021-11-24 17:59:55
【问题描述】:

截至目前,当我点击edit icon 时,form 被打开,我们曾经更改数据和save。 但现在我有一个要求,一旦用户click 在编辑图标上相同的row,除了certificateNo 应该是editable。和edit 按钮应替换为save。并且用户可以在那里保存数据,而无需转到任何其他页面。

如何解决这个问题?有什么建议吗?

 <tbody>

     {response.map((certificate: Certificate,index:number) => {
            return (
               <tr key={certificate.certificateNo}>
               <td>{certificate.certificateNo}</td>
               <td>{certificate.sponser}</td>
               <td>{certificate.protoColNo}</td>
               <td>{certificate.startDate}</td>
               <td>{certificate.endDate}</td>
               <td>{certificate.noOfSubjects}</td>
               <td>{certificate.country}</td>
               <td>{certificate.requestStatus}</td>
               <td>
           <div className="btn-group mr-2">
               <button className="btn btn-sm btn-outline-secondary" onClick={()=>updateCertificate(certificate,index)}>
               <i className="bi bi-pencil"></i>
               </button>
          </div>

【问题讨论】:

  • 你能提供一个你已经完成的代码沙箱链接吗?理想情况下,如果单击编辑按钮,您可以将控件从文本切换到输入。
  • 你能分享一些代码吗?最好是你的行组件。
  • 我添加了代码。

标签: javascript html reactjs react-hooks


【解决方案1】:

您需要某种能够识别正在编辑的行的方法,以及保存当前已编辑数据的位置。这可以通过使用状态来实现。

当您的数据数组中对象的 id 与当前选定的行匹配时(在您单击编辑按钮之后)返回一组包含 input 元素的行数据。如果id不匹配,则返回正常的行数据。

这是一个最小的工作示例。

const { useState } = React;

const data = [
  { id: 1, name: 'Rita', age: 22 },
  { id: 2, name: 'Sue', age: 42 },
  { id: 3, name: 'Bob', age: 12 }
]

function Example({ data }) {

  // Have states for the data, the current selected row
  // and the data that is currently being edited
  const [ rowData, setRowData ] = useState(data);
  const [ selectedRow, setSelectedRow ] = useState(0);
  const [ editData, setEditData ] = useState({});

  // Compiles the row data
  function getRows() {
    
    return rowData.map((obj, i) => {

      // Get the id, name, and age from the
      // current object
      const { id, name, age } = obj;
      
      // If the id of the current object equals
      // the selected row return a set of row data with input
      // elements (not id though) auto-populated with the
      // information from that object
      if (id === selectedRow) {
        return (
          <tr>
            <td>{editData.id}</td>
            <td>
              <input
                className="edit"
                type="text"
                name="name"
                value={editData.name}/>
            </td>
            <td>
              <input
                className="edit"
                type="text"
                name="age"
                value={editData.age}
              />
            </td>
            <button
              data-id={id}
              data-action="Save"
            >Save
            </button>
          </tr>
        );
      }
      
      // Otherwise return a set of non-editable
      // row data
      return (
        <tr>
          <td>{id}</td>
          <td>{name}</td>
          <td>{age}</td>
          <button
            data-id={id}
            data-action="Edit"
          >Edit
          </button>
        </tr>
      );
    
    });

  }

  // When a button has been clicked
  // Note: because we're using event delegation
  // (attaching listeners to the table element instead
  // of all the rows) we need to check that element
  // we clicked on is the button
  function handleClick(e) {
    
    const { nodeName } = e.target;
    
    if (nodeName === 'BUTTON') {
      
      const { id, action } = e.target.dataset;
      
      // If the button action is edit, set the
      // selected row state, and auto-populate the
      // editData state
      if (action === 'Edit') {
        setSelectedRow(+id);
        const obj = data.find(obj => obj.id === +id);
        setEditData({...obj});
      }
      
      // If the action is save filter out the matching
      // object from the data state, and then update the data
      // with the filtered object, plus the object in
      // the editData state, making sure you sort by id
      // otherwise the edited row will appear at the bottom
      // Then reset the states
      if (action === 'Save') {
        const filtered = data.filter(obj => obj.id !== selectedRow);
        const updated = [...filtered, editData];
        updated.sort((a, b) => a.id - b.id);
        setRowData(updated);
        setSelectedRow(0);
        setEditData({});
      }

    }
  
  }

  // When an input changes
  // Again we need to check that the element
  // that has changed is an input
  function handleChange(e) {
    
    const { nodeName } = e.target;
    
    // Update the editData state using the input
    // name and value
    if (nodeName === 'INPUT') {
      const { name, value } = e.target;
      setEditData({ ...editData, [name]: value });
    }
  
  }

  // We attach two listeners to the table element
  // One to catch clicks from the button
  // The other to catch changes to the inputs if
  // we're in edit mode
  return (
    <table
      onClick={handleClick}
      onChange={handleChange}
    >
      <tr class="heading">
        <td>ID</td>
        <td>Name</td>
        <td>Age</td>
      </tr>
      <tbody>
        {getRows()}
      </tbody>
    </table>
  );
};

ReactDOM.render(
  <Example data={data} />,
  document.getElementById('react')
);
table { border: 1px solid #898989; border-collapse: collapse; }
td, input { width: 75px; text-align: center; }
td { padding: 0.2em; border: 1px solid #898989; }
.heading { background-color: #efefef; text-align: center; font-weight: 600; }
.edit { background-color: #ffffcc; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="react"></div>

【讨论】:

    猜你喜欢
    • 2018-02-01
    • 1970-01-01
    • 2015-09-24
    • 2011-12-13
    • 2019-03-12
    • 1970-01-01
    • 2015-05-21
    • 2021-09-18
    • 1970-01-01
    相关资源
    最近更新 更多