I'm using Ant Design Editable Table where there is an operation
column where there is an edit
button. I have 2 other columns which are date
and value
. So what I want to have is when I press on the edit button for a specific row, I want to be able to change the date
using <DatePicker />
component from Ant Design. I have not been able to find a solution anywhere online for me. What I have right now is:
EditableTable.js
import React, { useState } from "react";
import { Table, Form, Button, DatePicker } from "antd";
import EditableCell from "./EditableCell";
const OtherLocsTable = ({ data, setData }) => {
const [form] = Form.useForm();
const [editingKey, setEditingKey] = useState("");
const isEditing = (record) => record.key === editingKey;
const edit = (record) => {
form.setFieldsValue({
date: "",
measurement: "",
...record,
});
setEditingKey(record.key);
};
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: "Date",
dataIndex: "date",
key: "date",
editable: true,
},
{
title: "Measurement",
dataIndex: "measurement",
key: "measurement",
editable: true,
},
{
title: "Operation",
dataIndex: "operation",
render: (_, record) => {
const editable = isEditing(record);
const lastElement = [...data].pop();
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>
</span>
) : (
<>
<Typography.Link
disabled={editingKey !== ""}
onClick={() => edit(record)}
>
Edit
</Typography.Link>
{data.length > 1 ? (
record.key === lastElement.key ? (
<Typography.Link
type="danger"
disabled={editingKey !== ""}
onClick={() => deleteRow(record)}
style={{
marginLeft: 15,
}}
>
Delete
</Typography.Link>
) : null
) : null}
</>
);
},
},
];
const mergedColumns = columns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
inputType:
col.dataIndex === loc
? "number"
: col.dataIndex === "date"
? "date"
: "text",
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record),
}),
};
});
return (
<>
<Popconfirm title="Confirm save changes?" onConfirm={handleSubmit}>
<Button
key="submit"
style={{
marginBottom: "1em",
width: "100%",
backgroundColor: "green",
}}
>
Save Changes
</Button>
</Popconfirm>
<Form form={form} component={false}>
<Table
components={{
body: {
cell: EditableCell,
},
}}
bordered
dataSource={data}
columns={mergedColumns}
rowClassName="editable-row"
pagination={{
onChange: cancel,
}}
rowKey="date"
/>
</Form>
</>
);
};
}
EditableCell.j
import React from "react";
import { Form, Input, InputNumber, DatePicker } from "antd";
import moment from "moment";
const EditableCell = ({
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
}) => {
const inputNode =
inputType === "number" ? (
<Form.Item
style={{ margin: 0 }}
name={dataIndex}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
>
<InputNumber formatter={(value) => value} parser={(value) => value} />
</Form.Item>
) : inputType === "date" ? (
<FormItem
style={{ margin: 0 }}
name={dataIndex}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
initialValue={moment(record[dataIndex])}
>
<DatePicker />
</FormItem>
) : (
<Form.Item
style={{ margin: 0 }}
name={dataIndex}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
>
<Input />
</Form.Item>
);
return <td {...restProps}>{editing ? inputNode : children}</td>;
};
export default EditableCell;
UPDATE
Currently with the code I have, I'm getting an error where it says date.clone is not a function
I found a solution
EditableTable.js
import React, { useState } from "react";
import { Table, Form, Button, DatePicker } from "antd";
import moment from 'moment';
import EditableCell from "./EditableCell";
const OtherLocsTable = ({ data, setData }) => {
const [form] = Form.useForm();
const [editingKey, setEditingKey] = useState("");
const isEditing = (record) => record.key === editingKey;
const edit = (record) => {
const {date, measurement} = record;
form.setFieldsValue({
date: (date) ? moment(date) : "",
measurement: measurement || ""
});
setEditingKey(record.key);
};
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: "Date",
dataIndex: "date",
key: "date",
editable: true,
},
{
title: "Measurement",
dataIndex: "measurement",
key: "measurement",
editable: true,
},
{
title: "Operation",
dataIndex: "operation",
render: (_, record) => {
const editable = isEditing(record);
const lastElement = [...data].pop();
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>
</span>
) : (
<>
<Typography.Link
disabled={editingKey !== ""}
onClick={() => edit(record)}
>
Edit
</Typography.Link>
{data.length > 1 ? (
record.key === lastElement.key ? (
<Typography.Link
type="danger"
disabled={editingKey !== ""}
onClick={() => deleteRow(record)}
style={{
marginLeft: 15,
}}
>
Delete
</Typography.Link>
) : null
) : null}
</>
);
},
},
];
const mergedColumns = columns.map((col) => {
if (!col.editable) {
return col;
}
return {
...col,
onCell: (record) => ({
record,
inputType:
col.dataIndex === loc
? "number"
: col.dataIndex === "date"
? "date"
: "text",
dataIndex: col.dataIndex,
title: col.title,
editing: isEditing(record),
}),
};
});
return (
<>
<Popconfirm title="Confirm save changes?" onConfirm={handleSubmit}>
<Button
key="submit"
style={{
marginBottom: "1em",
width: "100%",
backgroundColor: "green",
}}
>
Save Changes
</Button>
</Popconfirm>
<Form form={form} component={false}>
<Table
components={{
body: {
cell: EditableCell,
},
}}
bordered
dataSource={data}
columns={mergedColumns}
rowClassName="editable-row"
pagination={{
onChange: cancel,
}}
rowKey="date"
/>
</Form>
</>
);
};
}
EditableCell.j
import React from "react";
import { Form, Input, InputNumber, DatePicker } from "antd";
import moment from "moment";
const EditableCell = ({
editing,
dataIndex,
title,
inputType,
record,
index,
children,
...restProps
}) => {
const inputNode =
inputType === "number" ? (
<Form.Item
style={{ margin: 0 }}
name={dataIndex}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
>
<InputNumber formatter={(value) => value} parser={(value) => value} />
</Form.Item>
) : inputType === "date" ? (
<FormItem
style={{ margin: 0 }}
name={dataIndex}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
>
<DatePicker formate="DD-MM-YYYY" />
</FormItem>
) : (
<Form.Item
style={{ margin: 0 }}
name={dataIndex}
rules={[
{
required: true,
message: `Please Input ${title}!`,
},
]}
>
<Input />
</Form.Item>
);
return <td {...restProps}>{editing ? inputNode : children}</td>;
};
export default EditableCell;