인프런 커뮤니티 질문&답변
editable 구현 관련 문의 드립니다.
작성
·
604
0
antd 의 테이블 구현 관련 궁금한 부분을 문의 드리고 싶습니다.
antd 의 EditableTable, ResizableTitle, infinite scroll(react)를 적용해 보려하고 있습니다.
1. 테이블 헤드 가로 사이즈 변경이 먹지 않습니다. (예제 코드를 약간 변경해서 적용했습니다.)
2. 편집시 <td> padding과 Edit button 클릭시 td 안에 <input> padding 을 유지시 셀의 세로 높이가 바뀌는 문제가 있어서
Edit button 클릭시에도 동일하게 padding를 유지하도록 <td> className을 주어 padding를 주려고 합니다.
어느 부분이 잘못되어 있는지 코드 체크 부탁드립니다.
// import { VariableSizeGrid as Grid } from 'react-window';
// import ResizeObserver from 'rc-resize-observer';
// import classNames from 'classnames';
import React, { useState, useEffect, useRef } from 'react';
import { Resizable } from 'react-resizable';
import { Table, Input, InputNumber, Popconfirm, Form } from 'antd';
import styled, { createGlobalStyle } from 'styled-components';
const Global = createGlobalStyle`
.editable-row,
.ant-form-item-explain {
position: absolute;
top: 100%;
font-size: 12px;
}
table thead tr th { height: 10px;}
table tbody tr th { height: 10px;}
.editable row { height: 10px;}
#components-table-demo-resizable-column .react-resizable {
position: relative;
background-clip: padding-box;
}
#components-table-demo-resizable-column .react-resizable-handle {
position: absolute;
right: -5px;
bottom: 0;
z-index: 1;
width: 10px;
height: 100%;
cursor: col-resize;
}
.antd-table > tr > td {
padding: 0;
}
.antd-form-control-input-content > input {
padding: 11px 11px;
}
`;
const originData = [];
for (let i = 0; i < 100; i++) {
originData.push({
key: i.toString(),
name: `Edrward ${i}`,
age: i,
address: `London Park no. ${i}`,
// description: name + ' ' + age +' '+ address,
});
}
const ResizableTitle = props => {
const { onResize, width, ...restProps } = props;
if (!width) {
return <th {...restProps} />;
}
return (
<Resizable
width={width}
height={0}
handle={
<span
className="react-resizable-handle"
onClick={e => {
e.stopPropagation();
}}
/>
}
onResize={onResize}
draggableOpts={{ enableUserSelectHack: false }}
>
<th {...restProps} />
</Resizable>
);
};
const EditableCell = ({
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
}) => {
const inputNode = inputType === 'number' ? <InputNumber /> : <Input />;
return (
========================================
{editing ?
(
<td {...restProps} className="padding0">
<Form.Item
name={dataIndex}
style={{
margin: 0,
}}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
>
{inputNode}
</Form.Item>
</td>
) : (
<td {...restProps}>
children
</td>
)
}
);
};
============================================
const EditableTable = () => {
const [form] = Form.useForm();
const [data, setData] = useState(originData);
const [editingKey, setEditingKey] = useState('');
const isEditing = (record) => record.key === editingKey;
const edit = (record) => {
form.setFieldsValue({
name: '',
age: '',
address: '',
...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',
width: 100,
editable: true,
sorter: (a, b) => a.name.length - b.name.length,
},
{
title: 'age',
dataIndex: 'age',
width: 80,
editable: true,
sorter: (a, b) => a.age - b.age,
},
{
title: 'address',
dataIndex: 'address',
width: 200,
editable: true,
sorter: (a, b) => a.address.length - b.address.length,
},
{
title: 'operation',
dataIndex: 'operation',
render: (_, record) => {
const editable = isEditing(record);
return editable ? (
<span>
<a
href="javascript:;"
onClick={() => save(record.key)}
style={{
marginRight: 8,
}}
>
Save
</a>
{/* <Popconfirm title="Sure to cancel?" onConfirm={cancel}>
<a>Cancel</a>
</Popconfirm> */}
<a href="javascript:;" onClick={cancel} style={{ marginRight: 8 }}>
Cancel
</a>
</span>
) : (
<a disabled={editingKey !== ''} onClick={() => edit(record)}>
Edit
</a>
);
},
},
];
const handleResize = index => (e, { size }) => {
this.setState(({ columns }) => {
const nextColumns = [...columns];
nextColumns[index] = {
...nextColumns[index],
width: size.width,
};
return { columns: nextColumns };
});
};
const mergedColumns = columns.map((col, index) => {
if (!col.editable) {
return col;
}
return {
...col,
onHeaderCell: column => ({
width: column.width,
onResize: handleResize(index),
}),
onCell: (record) => ({
record,
inputType: col.dataIndex === 'age' ? 'number' : 'text',
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record),
}),
};
});
const onChange = (pagination, filters, sorter, extra) => {
console.log('params', pagination, filters, sorter, extra);
}
return (
<Form form={form} component={false}>
<Table
components={{
header: {
cell: ResizableTitle,
},
body: {
cell: EditableCell,
},
}}
expandable={{
expandedRowRender: record => <p style={{ margin: 0 }}>{record.description}</p>,
rowExpandable: record => record.name !== 'Not Expandable',
}}
bordered
dataSource={data}
columns={mergedColumns}
rowClassName="editable-row"
onChange={onChange}
scroll={{ y: 400 }}
pagination={false}
/>
</Form>
);
};
export default EditableTable;답변
답변을 기다리고 있는 질문이에요
첫번째 답변을 남겨보세요!




