UNPKG

app-base-web

Version:
197 lines (183 loc) 4.64 kB
import React, { useContext, useState, useEffect, useRef } from 'react'; import { Table, Input, Button, Popconfirm, Form } from 'antd'; import { EditOutlined } from '@ant-design/icons'; const EditableContext = React.createContext(); const EditableRow = ({ index, ...props }) => { const [form] = Form.useForm(); return ( <Form form={form} component={false}> <EditableContext.Provider value={form}> <tr {...props} /> </EditableContext.Provider> </Form> ); }; const EditableCell = ({ title, editable, children, dataIndex, record, handleSave, ...restProps }) => { const [editing, setEditing] = useState(false); const inputRef = useRef(); const form = useContext(EditableContext); useEffect(() => { if (editing) { inputRef.current.focus(); } }, [editing]); const toggleEdit = () => { setEditing(!editing); form.setFieldsValue({ [dataIndex]: record[dataIndex], }); }; const save = async e => { try { const values = await form.validateFields(); toggleEdit(); handleSave({ ...record, ...values }); } catch (errInfo) { console.log('Save failed:', errInfo); } }; let childNode = children; if (editable) { childNode = editing ? ( <Form.Item style={{ margin: 0, }} name={dataIndex} > <Input ref={inputRef} onPressEnter={save} onBlur={save} /> </Form.Item> ) : ( <div style={{ paddingRight: 24, display:'flex', alignItems: 'center', justifyContent: 'space-between' }} onClick={toggleEdit} > {children} <EditOutlined /> </div> ); } return <td {...restProps}>{childNode}</td>; }; export default class EditableTable extends React.Component { constructor(props) { super(props); this.columns = [ { title: 'key', dataIndex: 'paramKey', width: '40%', editable: true, }, { title: 'value', dataIndex: 'paramValue', width: '40%', editable: true, }, { title: '操作', dataIndex: 'operation', width: '20%', render: (text, record) => this.state.dataSource.length >= 1 ? ( <Popconfirm title="确定删除吗?" onConfirm={() => this.handleDelete(record.key)}> <a>删除</a> </Popconfirm> ) : null, }, ]; this.state = { dataSource: this.props.dataSource?this.props.dataSource:[], count: this.props.dataSource?this.props.dataSource.length:0, }; } handleDelete = key => { const dataSource = [...this.state.dataSource]; this.setState({ dataSource: dataSource.filter(item => item.key !== key), }); }; handleAdd = () => { const { count, dataSource } = this.state; const newData = { key: count, paramKey: "", paramValue: "", }; this.setState({ dataSource: [...dataSource, newData], count: count + 1, }); }; handleSave = row => { const newData = [...this.state.dataSource]; const index = newData.findIndex(item => row.key === item.key); const item = newData[index]; newData.splice(index, 1, { ...item, ...row }); this.setState({ dataSource: newData, }); }; render() { console.log('this.state.dataSource',this.state.dataSource) const { dataSource } = this.state; const components = { body: { row: EditableRow, cell: EditableCell, }, }; const columns = this.columns.map(col => { if (!col.editable) { return col; } return { ...col, onCell: record => ({ record, editable: col.editable, dataIndex: col.dataIndex, title: col.title, handleSave: this.handleSave, }), }; }); return ( <div> <Button onClick={this.handleAdd} type="primary" style={{ marginBottom: 16, }} > 新增行 </Button> <Table components={components} rowClassName={() => 'editable-row'} bordered dataSource={dataSource} columns={columns} //去掉分页 pagination={ false } scroll={{ y: 300 }} /> </div> ); } }