React基于antd table实现行内可编辑表格

166 阅读1分钟
import React from 'react';import { Table, Input, InputNumber, Form, Select } from 'antd';import { OPTION_TYPE } from '../../constants/typeConstant';import event, { EVENT_TYPE } from '../../utils/event';import Common from '../../utils/common';// 支持按行编辑的table// 必传参数:columns、onSave、newRowKey、updateList// column以editable标识是否可编辑, inputType标识编辑时为input还是select等, optionList标识为select时的可选值const EditableContext = React.createContext();class EditableCell extends React.Component {  getInput = () => {    const {inputType, mode, optionList} = this.props;    switch(inputType){        case 'input':            return <Input style={{width: '100%'}}/>;          case 'number':            return <InputNumber style={{width: '100%'}}/>;         case 'select':            return <Select style={{width: '100%'}}                showSearch                allowClear                mode={mode || 'multiple'}                optionFilterProp="children"                   >                    {optionList?.map((item) => (                        <Select.Option value={item.value} key={item.value}>                            {item.label}                        </Select.Option>                    ))                    }                </Select>                }    return <Input/>;  };  renderCell = ({ getFieldDecorator }) => {    debugger    const {      editing,      dataIndex,      title,      inputType,      required,      record,      index,      children,      ...restProps    } = this.props;    return (      <td {...restProps}>        {editing ? (          <Form.Item style={{ margin: 0 }}>            {getFieldDecorator(dataIndex, {              rules: [                {                  required: required == true || false,                  message: required == true ? `请输入 ${title}!`: ''                }              ],              initialValue: (record[dataIndex] && Array.isArray(record[dataIndex])) ?                 record[dataIndex]?.map(item => Common.types(item).isObject ? item.value : item) :                 (Common.types(record[dataIndex]).isObject ? record[dataIndex].value : record[dataIndex])            })(this.getInput())}          </Form.Item>        ) : (          children        )}      </td>    );  };  render() {    return <EditableContext.Consumer>{this.renderCell}</EditableContext.Consumer>;  }}class EditableTable extends React.Component {  constructor(props) {    super(props);    this.state = { editingKey: '' };  }  componentDidMount(){    event.addListener(EVENT_TYPE.ADD_ROW_IN_EDITABLE_TABLE, this.editNewRow);  }  componentWillUnmount(){    event.removeListener(EVENT_TYPE.ADD_ROW_IN_EDITABLE_TABLE, this.editNewRow);  }  isEditing = record => record.key === this.state.editingKey;  // 取消  cancel = (key) => {    const {updateList} = this.props;    updateList && updateList();    this.setState({ editingKey: '' });  };  //保存  save(form, key, onSave) {    const { updateList} = this.props;    form.validateFields((error, row) => {      if (error) {        return;      }      //调用自定义保存方法      onSave(row);      updateList && updateList();      this.setState({ editingKey: '' });    });  }  // 切换为编辑状态  edit(key) {    this.setState({ editingKey: key });  }  // 新增行切换为编辑状态  editNewRow = () =>{    const {newRowKey} = this.props;    this.setState({ editingKey: newRowKey || 'new_row' });  }  formatColumns = () => {    const {columns, handleView, handleDelete} = this.props;    const newColumns = [...columns];    return newColumns?.map(column => {        if(column?.dataIndex == 'operation'){            const viewOption =  column.options?.find(option => option.type === OPTION_TYPE.VIEW);            const editOption =  column.options?.find(option => option.type === OPTION_TYPE.EDIT);            const deleteOption =  column.options?.find(option => option.type === OPTION_TYPE.DELETE);            column.render = (text, record) => {                const { editingKey } = this.state;                const editable = this.isEditing(record);                return <>                {                  viewOption && !editable &&                  viewOption?.render(record)                }                {editOption &&(                  editable ? (                    <span>                      <EditableContext.Consumer>                        {form => (                          <a                              onClick={() => this.save(form, record.key, editOption.onSave)}                              style={{ marginRight: 10 }}                          >                            保存                          </a>                        )}                      </EditableContext.Consumer>                      <a                          onClick={() => this.cancel(record.key)}                      >                          取消                       </a>                    </span>                  ) : (                    <a disabled={editingKey !== ''}                         onClick={() => this.edit(record.key)}                        style={{ marginRight: 10 }}                    >                      编辑                    </a>                  )                )}                {                  deleteOption && !editable &&                  deleteOption?.render(record)                }                </>            }        }        if(!column.editable) {          return column;        }        return {        ...column,        onCell: record => ({            record,            inputType: column.inputType,            dataIndex: column.dataIndex,            title: column.title,            required: column.required,            mode: column.mode,             optionList: column.optionList,            editing: this.isEditing(record)        })        };    });  }  render() {    const {columns, ...restProps} = this.props;    const components = {      body: {        cell: EditableCell      }    };    return (      <EditableContext.Provider value={this.props.form}>        <Table            components={components}            columns={this.formatColumns()}            {...restProps}        />      </EditableContext.Provider>    );  }}export default Form.create()(EditableTable);