Use Antd to implement editable cells & tables

Posted on 2022-03-13  182 Views


Recently, I encountered the need to implement a table with editable cells and support pop-up editing in the project, check the official documentation of Antd, here is based on the official simplified version, easy to get started.

Refinement of requirements


Suppose there is a table as shown in the figure, and now you need to change the Grade field to <InputNumber> component, requiring that the changed value be stored in the local state every time the value is modified. In addition, after clicking the pencil button, the modal window will open, and the user can also modify the value in the modal window, and the modification also needs to be synchronized to the local state.

Core idea

  • Encapsulate an editable cell and write data back to storage using the onChange hook > < InputNumber.
  • All editable cell components are implemented using the render function of columns in ant-table.
  • Modal windows are also rendered by the render function of columns in ant-table, accepting the current row as props and modifying it in the same data source as the table.

Implement the Editable Cell component

Here the data source is simplified into a state storage, which can be memored or put into Redux when actually used, without repeating.

const [tableData, setTableData] = useState(dataSource);

const EditableInputNumber = (props) => {
  const { text, field, record, tableData, setTableData } = props
  const onValueChange = useCallback((value) => {
    let newData = [...tableData]
    const idx = newData.findIndex(item => item.displayId === record.displayId)
    if (idx !== -1) {
      newData[idx][field] = value
      setTableData(newData)
    }
  }, [tableData, field, record]);

return (
    <>
      
    
  )
}

In antd's columns, configure the columns to be edited as follows:

{
  title: 'Grade',
  dataIndex: 'grade',
  key: 'grade',
  render: (text, record) => {
  return (
    
  )}
}

The advantage of writing this way is that it saves a lot of time to use official documents to configure the provider, form, and onRow method, and the disadvantage is that it deepens the coupling between components, but considering that such tables do not carry out deep reuse in actual business, this simple and crude configuration method is adopted.

Implement modal windows

There are two points to consider when implementing modal windows:
+ How to get the data of the current row
+ How to synchronize modified data back to the data source
We use antd's form component to control synchronization between data. Get the form instance through the Form.useForm() hook, and then synchronize the current row data into the form through form.setFieldsValue(), and form.validateFields().then() to synchronize the submitted form data back to the data source. The specific implementation code is as follows:

const [editRowForm] = Form.useForm()
const [modalVisible, setModalVisible] = useState(false)
const [currentRow, setCurrentRow] = useState()
const [tableData, setTableData] = useState(dataSource)

Edit the button's callback function
const onRowEdit = useCallback((rowRecord) => {
  setCurrentRow(rowRecord)
  editRowForm.setFieldsValue(rowRecord)
  showEditModal()
})

The callback function for the form submission button
const onEditModalSubmit = useCallback(() => {
  editRowForm.validateFields().then((values) => {
    let newTableData = [ ...tableData ]
    const targetIndex = tableData.findIndex(record => record.displayId === currentRow.displayId)
    newTableData[targetIndex] = { ... values }
    setTableData(newTableData)
    closeEditModal()
  })
}, [tableData, currentRow])

Modal window assembly

    
    
    
  }>
  
ID
Name
Grade

In addition, you need to bind the callback of the edit button (pencil) to the onRowEdit function, and the same goes for the delete button.

{
  title: 'Actions',
  dataIndex: 'actions',
  key: 'actions',
  width: 120,
  render: (text, record) => {
    return (
      <>
        

The final effect

Editable cells:

Modal windows