
- import React, { useState } from 'react';
- import 'antd/dist/antd.css';
- // import './index.css';
- import { MenuOutlined } from '@ant-design/icons';
- import { Table } from 'antd';
- import { arrayMoveImmutable } from 'array-move';
- import { Form, Input, InputNumber, Popconfirm, Table, Typography } from 'antd';
-
- import {
- SortableContainer,
- SortableElement,
- SortableHandle,
- } from 'react-sortable-hoc';
-
- const originData = [
- {
- key: '1',
- name: 'John Brown',
- age: 32,
- address: 'New York No. 1 Lake Park',
- index: 0,
- },
- {
- key: '2',
- name: 'Jim Green',
- age: 42,
- address: 'London No. 1 Lake Park',
- index: 1,
- },
- {
- key: '3',
- name: 'Joe Black',
- age: 32,
- address: 'Sidney No. 1 Lake Park',
- index: 2,
- },
- ];
- const EditableCell = ({
- editing,
- dataIndex,
- title,
- inputType,
- record,
- index,
- children,
- ...restProps
- }) => {
- const inputNode = inputType === 'number' ? <InputNumber /> : <Input />;
- return (
- <td {...restProps}>
- {editing ? (
- <Form.Item
- name={dataIndex}
- style={{
- margin: 0,
- }}
- rules={[
- {
- required: true,
- message: `Please Input ${title}!`,
- },
- ]}
- >
- {inputNode}
- </Form.Item>
- ) : (
- children
- )}
- </td>
- );
- };
- const DragHandle = SortableHandle(() => (
- <MenuOutlined
- style={{
- cursor: 'grab',
- color: '#999',
- }}
- />
- ));
-
- const SortableItem = SortableElement((props) => <tr {...props} />);
- const SortableBody = SortableContainer((props) => <tbody {...props} />);
- const App = () => {
- // const [dataSource, setDataSource] = useState(data);
- const [form] = Form.useForm();
- const [data, setData] = useState(originData);
- const [editingKey, setEditingKey] = useState('');
- const isEditing = (record) => record.key === editingKey;
- const edit = (record) => {
- form.setFieldsValue({
- ...record,
- });
- setEditingKey(record.key);
- };
-
- const cancel = () => {
- setEditingKey('');
- };
-
- const save = async (key) => {
- try {
- const row = await form.validateFields();
- const newData = [...data];
- const index = newData.findIndex((item) => key === item.key);
- if (index > -1) {
- const item = newData[index];
- newData.splice(index, 1, {
- ...item,
- ...row,
- });
- setData(newData);
- setEditingKey('');
- } else {
- newData.push(row);
- setData(newData);
- setEditingKey('');
- }
- } catch (errInfo) {
- console.log('Validate Failed:', errInfo);
- }
- };
-
- const columns = [
- {
- title: 'Name',
- dataIndex: 'name',
- className: 'drag-visible',
- editable: true,
- },
- {
- title: 'Age',
- dataIndex: 'age',
- editable: true,
- },
- {
- title: 'Address',
- dataIndex: 'address',
- editable: true,
- },
- {
- title: 'operation',
- dataIndex: 'operation',
- render: (_, record) => {
- const editable = isEditing(record);
- return editable ? (
- <span>
- <Typography.Link
- onClick={() => save(record.key)}
- style={{
- marginRight: 8,
- }}
- >
- 保存
- </Typography.Link>
- <Popconfirm title="Sure to cancel?" onConfirm={cancel}>
- <a>删除</a>
- </Popconfirm>
- </span>
- ) : (
- <div style={{ display: 'flex' }}>
- <Typography.Link
- disabled={editingKey !== ''}
- onClick={() => edit(record)}
- >
- 编辑
- </Typography.Link>
- <div style={{ marginLeft: '16px' }}>
- <DragHandle />
- </div>
- </div>
- );
- },
- },
- ];
- const onSortEnd = ({ oldIndex, newIndex }) => {
- if (oldIndex !== newIndex) {
- const newData = arrayMoveImmutable(
- data.slice(),
- oldIndex,
- newIndex
- ).filter((el) => !!el);
- console.log('Sorted items: ', newData);
- setData(newData);
- }
- };
- const DraggableContainer = (props) => (
- <SortableBody
- useDragHandle
- disableAutoscroll
- helperClass="row-dragging"
- onSortEnd={onSortEnd}
- {...props}
- />
- );
- const DraggableBodyRow = ({ className, style, ...restProps }) => {
- // function findIndex base on Table rowKey props and should always be a right array index
- const index = data.findIndex((x) => x.index === restProps['data-row-key']);
- return <SortableItem index={index} {...restProps} />;
- };
-
- const mergedColumns = columns.map((col) => {
- if (!col.editable) {
- return col;
- }
- return {
- ...col,
- onCell: (record) => ({
- record,
- inputType: col.dataIndex === 'age' ? 'number' : 'text',
- dataIndex: col.dataIndex,
- title: col.title,
- editing: isEditing(record),
- }),
- };
- });
- return (
- <Form form={form} component={false}>
- <Table
- pagination={false}
- // dataSource={dataSource}
- // columns={columns}
- rowKey="index"
- dataSource={data}
- columns={mergedColumns}
- components={{
- body: {
- cell: EditableCell,
- wrapper: DraggableContainer,
- row: DraggableBodyRow,
- },
- }}
- />
- </Form>
- );
- };
- export default App;