React中插入可编辑行的table表格

参考antd官网中table的可编辑行的demo Ant Design
下面的demo在官网的基础上进行了部分优化,可直接运行,实现的功能如下:
  • 涉及到数字的单元格,加上千分符
  • 点击编辑按钮,当前行可编辑,其他行不可编辑
  • 编辑状态下,带数字的单元格去掉千分符
  • 点击保存或取消之后,再加上千分符
    在这里插入图片描述

表格的原始数据

let modelList = [
  {
    key: "1",
    name: "Edrward 0",
    income: 3342.33,
    address: "London Park no. 0",
    operation: ""
  },
  {
    key: "2",
    name: "Edrward 1",
    income: 11432.33,
    address: "London Park no. 1",
    operation: ""
  },
  {
    key: "3",
    name: "Edrward 3",
    income: 55312.33,
    address: "London Park no. 3",
    operation: ""
  }
]

单元格

class EditableCell extends React.Component {
  renderCell = ({ getFieldDecorator }) => {
    const {
      editing, dataIndex, title, Inputs, record, index, children,
      ...restProps
    } = this.props;

    return (
      <td {...restProps} className='my-cell-td'>
        {editing ? (
          dataIndex == 'income' ?
            < Item style={{ margin: 0 }}>
              {getFieldDecorator(dataIndex, {
                rules: [{
                  required: true,
                  pattern: new RegExp(/^\d+\.?(\d{1,2})?$/),
                  message: '小数点后保留2位小数'
                }],
                initialValue: record[dataIndex] == '-' ? '' : record[dataIndex].replace(/,/g, ''),
              })(
                <Inputs />
              )}
            </Item> : < Item style={{ margin: 0 }}>
              {getFieldDecorator(dataIndex, {
                rules: [{ required: true, message: `请输入 ${title}!` }],
                initialValue: record[dataIndex],
              })(
                <Inputs />
              )}
            </Item>
        ) : children
        }
      </td>
    );
  };
  render() {
    return <Consumer>{this.renderCell}</Consumer>;
  }
}

import React from 'react';
import { Table, Form, Input, Popconfirm } from 'antd';

const { Item } = Form
const { Provider, Consumer } = React.createContext()//组件之间传值

class TableRow extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      editingKey: '',
      data: modelList
    }
  }
  componentDidMount() {
    modelList.forEach(item => {
      item.income = this.formatNumber(item.income)
    })
    this.setState({
      data: modelList
    })
  }
  //千分符
  formatNumber = num => {
    if (isNaN(num)) {
      throw new TypeError("num is not a number");
    }
    var groups = (/([\-\+]?)(\d*)(\.\d+)?/g).exec("" + num),
      mask = groups[1],            //符号位 
      integers = (groups[2] || "").split(""), //整数部分 
      decimal = groups[3] || "",       //小数部分 
      remain = integers.length % 3;

    var temp = integers.reduce(function (previousValue, currentValue, index) {
      if (index + 1 === remain || (index + 1 - remain) % 3 === 0) {
        return previousValue + currentValue + ",";
      } else {
        return previousValue + currentValue;
      }
    }, "").replace(/\,$/g, "");
    return mask + temp + decimal;
  }

  //判断是否可编辑
  isEditing = record => record.key == this.state.editingKey

  //是否展示编辑
  editable = (editable, editingKey, record) => {
    const ele = editable ? (
      <span style={{ display: 'block' }}>
        <Consumer>
          {
            form => (
              <a onClick={() => this.save(form, record.key)} style={{ marginRight: 8 }}>
                保存
        	  </a>
            )
          }
        </Consumer>
        <Popconfirm
          title="是否确定取消?"
          onConfirm={this.cancel}
          okText="确定"
          cancelText="取消"
        >
          <a>取消</a>
        </Popconfirm>
      </span>
    ) : (
        <a disabled={editingKey !== ''} onClick={() => this.edit(record.key)}>
          编辑
        </a>
      );
    return ele
  }

  //编辑
  edit = (key) => {
    this.setState({
      editingKey: key
    })
  }

  //保存
  save = (form, key) => {

    form.validateFields((error, row) => {
      if (error) {
        return
      }

      for (let i in row) {
        //!isNaN(Number(item[i].replace(/,/g, '')) 判断清除掉逗号的元素是不是数字类型
        row[i] = !isNaN(parseFloat(row[i])) ? this.formatNumber(row[i]) : row[i]
      }

      const newData = this.state.data
      const index = newData.findIndex(item => item.key === key)

      if (index > -1) {
        const item = newData[index];

        newData.splice(index, 1, {
          ...item,
          ...row,
        });
      }

      this.setState({
        editingKey: '',
        data: newData
      })
    })
  }

  //取消
  cancel = () => {
    this.setState({
      editingKey: ''
    })
  }

  init = () => {
    this.columns = [
      {
        title: 'name',
        dataIndex: 'name',
        editable: true,
      },
      {
        title: 'income',
        dataIndex: 'income',
        editable: true,
      },
      {
        title: 'address',
        dataIndex: 'address',
        editable: true,
      },
      {
        title: 'operation',
        dataIndex: 'operation',
        render: (text, record, index) => {
          const { editingKey } = this.state;
          const editable = this.isEditing(record);
          return <div>
            {
              this.editable(editable, editingKey, record)
            }
          </div>
        }
      },
    ]
  }

  render() {
    this.init()
    const components = {
      body: {
        cell: EditableCell,
      },
    };

    const columns = this.columns.map(col => {

      if (!col.editable) {
        return col;
      }
      return {
        ...col,
        onCell: record => ({
          record,
          Inputs: Input,
          dataIndex: col.dataIndex,
          title: col.title,
          editing: this.isEditing(record),
        }),
      };
    });

    return (
      <Provider value={this.props.form}>
        < Table
          components={components}//覆盖默认的 table 元素
          columns={columns}
          dataSource={this.state.data}
          pagination={false}
        />
      </Provider >
    )
  }
}
export default Form.create({
  onValuesChange(props, changeValues, allValues) {
    // console.log(allValues);
  }
})(TableRow)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值