I have ant design form and table side by side,When I fill the form data and click on add entity button
the data should be displayed in the table. Now the data does get rendered when I click on add entity but again when I fill the form and click on the add entity button the previous data gets disappeared, Now I know that I need to copy the previous data and I did that too but its not working.
My Problem:- The previous form state value which is rendered in the table gets disappeared when new form data is added
My query:- How and Where should I copy the previous object with the spread operator so that it does not get reset.
My code is
import { Card, Table } from "antd";
import { Form, Input, Button, Select, Space, AutoComplete } from "antd";
import { DeleteOutlined, PlusOutlined, SendOutlined } from "@ant-design/icons";
import { useState } from "react";
const ExampleComponent = (props) => {
// Destructuring props
const { intent_data, entity_data } = props;
const [dataSource, setDataSource] = useState([{}]);
// To handle the disable state of Select Entity Select DropDown
const [addentity,setAddEntity] = useState(false)
// Handler function passed to YES/NO Select Option
const addEntityHandler = (addEntity) => {
if(addEntity === 'no'){
setAddEntity(true)
}else{
setAddEntity(false)
}
}
const [form] = Form.useForm();
const onFinish = (values) => {
console.log(values);
form.resetFields();
const dataArr = [];
// Push values to array since dataSource takes array not an object
dataArr.push(values);
setDataSource(dataArr);
};
const columns = [
{
title: "Entity",
dataIndex: "entity_name",
key: "entity_name",
},
{
title: "Entity Value",
dataIndex: "entity_value",
key: "entity_value",
},
{
title: "Operation",
key: "operation",
render: (record: any) => (
<DeleteOutlined
style={{ color: "red" }}
onClick={() => console.log(record)}
/>
),
},
];
return (
<Card className="csi-project-card-0934">
<div className="example-layout">
<div style={{ flexBasis: "100%" }}>
<Form
form={form}
labelCol={{ span: 7 }}
wrapperCol={{ span: 10 }}
layout="horizontal"
colon={true}
onFinish={onFinish}
size="large"
>
{/* <h4>Create Example</h4> */}
<Form.Item
label="Select Intent"
name="intent_name"
className="csi-ant-form-item"
rules={[{ required: true, message: "Intent Cannot be Empty!" }]}
>
<Select>
{/* {intent_data?.map?.((value) => (
<Select.Option
key={value.intent_ID}
value={value.intent_name}
>
{value.intent_name}
</Select.Option>
))} */}
<Select.Option value="intent demo">Intent Demo</Select.Option>
<Select.Option value="intent test">Intent Test</Select.Option>
</Select>
</Form.Item>
<Form.Item
label="Enter Example"
name="example_name"
className="csi-ant-form-item"
hasFeedback
rules={[
{ required: true, message: "This Field Cannot be Empty!" },
({ getFieldValue }) => ({
validator(_, value) {
if (value.length < 4) {
return Promise.reject("Length too short");
}
return Promise.resolve();
},
}),
]}
>
<AutoComplete>
<Input allowClear/>
</AutoComplete>
</Form.Item>
<Form.Item
label="Do you want to add Entity"
name="add_entity"
className="csi-ant-form-item"
rules={[{ required: true, message: "This Cannot be Empty!" }]}
>
<Select placeholder="SELECT" onSelect={(addEntity) => addEntityHandler(addEntity)}>
<Select.Option value="yes">YES</Select.Option>
<Select.Option value="no">NO</Select.Option>
</Select>
</Form.Item>
<Form.Item
label="Select Entity"
name="entity_name"
className="csi-ant-form-item"
>
<Select disabled = {addentity}>
<Select.Option value="entity demo">Entity Demo</Select.Option>
<Select.Option value="entity test">Entity Test</Select.Option>
</Select>
</Form.Item>
<Form.Item
label="Select Value"
name="entity_value"
className="csi-ant-form-item"
hasFeedback
rules={[
{ required: true, message: "This Field Cannot be Empty!" },
]}
>
<AutoComplete>
<Input placeholder="Select Value from Example" />
</AutoComplete>
</Form.Item>
<Form.Item className="csi-ant-form-item">
<Button
key="submit"
type="primary"
htmlType="submit"
shape="round"
>
Add Entity <PlusOutlined />
</Button>
</Form.Item>
</Form>
</div>
<div
style={{
flexBasis: "100%",
display: "flex",
flexDirection: "column",
alignItems: "center",
}}
>
<Table
bordered
className="ib-table"
dataSource={dataSource}
columns={columns}
pagination={{ pageSize: 6 }}
rowKey={Math.random().toString()}
/>
<Button key="submit" type="primary" htmlType="submit" shape="round">
Submit <SendOutlined />
</Button>
</div>
</div>
</Card>
);
};
export default ExampleComponent;
The form data is stored in values object and the structure of values is
{
add_entity: "yes"
entity_name: "entity demo"
entity_value: "Test"
example_name: "Test"
intent_name: "intent demo"
}
One thing to note here is that dataSource state variable is array of objects, like
[{
add_entity: "yes"
entity_name: "entity demo"
entity_value: "Test"
example_name: "Test"
intent_name: "intent demo"
}]
My Expected Output is Below
Entity | Entity Value | Operation |
---|---|---|
entity demo | test | delete icon |
intent demo | test | delete icon |
CodePudding user response:
What if you try with
setDataSource(prevDataSource => [...prevDataSource, values]);
?
In the same way, to delete an item:
{
title: "Operation",
key: "operation",
render: (record) => (
<DeleteOutlined
style={{ color: "red" }}
onClick={() => {
setDataSource(prevDataSource => prevDataSource.filter(item => item.entity_name !== record.entity_name //entity_name or whatever id the item has ))
}}
/>
),
},
By the way, try to avoid using any whenever possible if you're using typescript. Here is how to:
import { Table } from 'antd';
import { ColumnsType } from 'antd/es/table';
interface User {
key: number;
name: string;
}
const columns: ColumnsType<User> = [
{
key: 'name',
title: 'Name',
dataIndex: 'name',
},
];
const data: User[] = [
{
key: 0,
name: 'Jack',
},
];
export default () => (
<>
<Table<User> columns={columns} dataSource={data} />
/* JSX style usage */
<Table<User> dataSource={data}>
<Table.Column<User> key="name" title="Name" dataIndex="name" />
</Table>
</>
);