• 表格拖拽和可编辑行功能


    1. import React, { useState } from 'react';
    2. import 'antd/dist/antd.css';
    3. // import './index.css';
    4. import { MenuOutlined } from '@ant-design/icons';
    5. import { Table } from 'antd';
    6. import { arrayMoveImmutable } from 'array-move';
    7. import { Form, Input, InputNumber, Popconfirm, Table, Typography } from 'antd';
    8. import {
    9. SortableContainer,
    10. SortableElement,
    11. SortableHandle,
    12. } from 'react-sortable-hoc';
    13. const originData = [
    14. {
    15. key: '1',
    16. name: 'John Brown',
    17. age: 32,
    18. address: 'New York No. 1 Lake Park',
    19. index: 0,
    20. },
    21. {
    22. key: '2',
    23. name: 'Jim Green',
    24. age: 42,
    25. address: 'London No. 1 Lake Park',
    26. index: 1,
    27. },
    28. {
    29. key: '3',
    30. name: 'Joe Black',
    31. age: 32,
    32. address: 'Sidney No. 1 Lake Park',
    33. index: 2,
    34. },
    35. ];
    36. const EditableCell = ({
    37. editing,
    38. dataIndex,
    39. title,
    40. inputType,
    41. record,
    42. index,
    43. children,
    44. ...restProps
    45. }) => {
    46. const inputNode = inputType === 'number' ? <InputNumber /> : <Input />;
    47. return (
    48. <td {...restProps}>
    49. {editing ? (
    50. <Form.Item
    51. name={dataIndex}
    52. style={{
    53. margin: 0,
    54. }}
    55. rules={[
    56. {
    57. required: true,
    58. message: `Please Input ${title}!`,
    59. },
    60. ]}
    61. >
    62. {inputNode}
    63. </Form.Item>
    64. ) : (
    65. children
    66. )}
    67. </td>
    68. );
    69. };
    70. const DragHandle = SortableHandle(() => (
    71. <MenuOutlined
    72. style={{
    73. cursor: 'grab',
    74. color: '#999',
    75. }}
    76. />
    77. ));
    78. const SortableItem = SortableElement((props) => <tr {...props} />);
    79. const SortableBody = SortableContainer((props) => <tbody {...props} />);
    80. const App = () => {
    81. // const [dataSource, setDataSource] = useState(data);
    82. const [form] = Form.useForm();
    83. const [data, setData] = useState(originData);
    84. const [editingKey, setEditingKey] = useState('');
    85. const isEditing = (record) => record.key === editingKey;
    86. const edit = (record) => {
    87. form.setFieldsValue({
    88. ...record,
    89. });
    90. setEditingKey(record.key);
    91. };
    92. const cancel = () => {
    93. setEditingKey('');
    94. };
    95. const save = async (key) => {
    96. try {
    97. const row = await form.validateFields();
    98. const newData = [...data];
    99. const index = newData.findIndex((item) => key === item.key);
    100. if (index > -1) {
    101. const item = newData[index];
    102. newData.splice(index, 1, {
    103. ...item,
    104. ...row,
    105. });
    106. setData(newData);
    107. setEditingKey('');
    108. } else {
    109. newData.push(row);
    110. setData(newData);
    111. setEditingKey('');
    112. }
    113. } catch (errInfo) {
    114. console.log('Validate Failed:', errInfo);
    115. }
    116. };
    117. const columns = [
    118. {
    119. title: 'Name',
    120. dataIndex: 'name',
    121. className: 'drag-visible',
    122. editable: true,
    123. },
    124. {
    125. title: 'Age',
    126. dataIndex: 'age',
    127. editable: true,
    128. },
    129. {
    130. title: 'Address',
    131. dataIndex: 'address',
    132. editable: true,
    133. },
    134. {
    135. title: 'operation',
    136. dataIndex: 'operation',
    137. render: (_, record) => {
    138. const editable = isEditing(record);
    139. return editable ? (
    140. <span>
    141. <Typography.Link
    142. onClick={() => save(record.key)}
    143. style={{
    144. marginRight: 8,
    145. }}
    146. >
    147. 保存
    148. </Typography.Link>
    149. <Popconfirm title="Sure to cancel?" onConfirm={cancel}>
    150. <a>删除</a>
    151. </Popconfirm>
    152. </span>
    153. ) : (
    154. <div style={{ display: 'flex' }}>
    155. <Typography.Link
    156. disabled={editingKey !== ''}
    157. onClick={() => edit(record)}
    158. >
    159. 编辑
    160. </Typography.Link>
    161. <div style={{ marginLeft: '16px' }}>
    162. <DragHandle />
    163. </div>
    164. </div>
    165. );
    166. },
    167. },
    168. ];
    169. const onSortEnd = ({ oldIndex, newIndex }) => {
    170. if (oldIndex !== newIndex) {
    171. const newData = arrayMoveImmutable(
    172. data.slice(),
    173. oldIndex,
    174. newIndex
    175. ).filter((el) => !!el);
    176. console.log('Sorted items: ', newData);
    177. setData(newData);
    178. }
    179. };
    180. const DraggableContainer = (props) => (
    181. <SortableBody
    182. useDragHandle
    183. disableAutoscroll
    184. helperClass="row-dragging"
    185. onSortEnd={onSortEnd}
    186. {...props}
    187. />
    188. );
    189. const DraggableBodyRow = ({ className, style, ...restProps }) => {
    190. // function findIndex base on Table rowKey props and should always be a right array index
    191. const index = data.findIndex((x) => x.index === restProps['data-row-key']);
    192. return <SortableItem index={index} {...restProps} />;
    193. };
    194. const mergedColumns = columns.map((col) => {
    195. if (!col.editable) {
    196. return col;
    197. }
    198. return {
    199. ...col,
    200. onCell: (record) => ({
    201. record,
    202. inputType: col.dataIndex === 'age' ? 'number' : 'text',
    203. dataIndex: col.dataIndex,
    204. title: col.title,
    205. editing: isEditing(record),
    206. }),
    207. };
    208. });
    209. return (
    210. <Form form={form} component={false}>
    211. <Table
    212. pagination={false}
    213. // dataSource={dataSource}
    214. // columns={columns}
    215. rowKey="index"
    216. dataSource={data}
    217. columns={mergedColumns}
    218. components={{
    219. body: {
    220. cell: EditableCell,
    221. wrapper: DraggableContainer,
    222. row: DraggableBodyRow,
    223. },
    224. }}
    225. />
    226. </Form>
    227. );
    228. };
    229. export default App;

  • 相关阅读:
    【PB续命05】WinHttp.WinHttpRequest的介绍与使用
    【spring cloud】(四)服务网关——gateway
    ACA-PEG-NH2,丙烯酰胺PEG氨基
    生成树Toolkit
    程序需要的代码
    英文转换-在线英文批量转换器免费
    【ai】tx2-nx:Yolo V4 直接安装与 测试
    山海鲸智慧工厂:制造业数字化的风向标
    《Linux图形驱动与桌面》之DMA-FENCE
    Java 基础_框架阶段核心面试题
  • 原文地址:https://blog.csdn.net/qq_45823368/article/details/132901383