How can I have a form inside the table of a List in antd design

I want to have a table and for each row I would like to be able to have a cell that has a form input for a field called label, how can I do this in antd design?
5 Replies
kapa.ai
kapa.ai3mo ago
Hi @BlackBearFTW. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To have a form inside the table of a List in Ant Design using refine, you can follow the approach demonstrated in the provided knowledge sources. Specifically, you can render a form input within a table cell by conditionally rendering the input field based on whether the row is in an editing state. Here is an example of how you can achieve this:
import React, { useState } from "react";
import { List, useTable, EditButton, SaveButton, Button } from "@refinedev/antd";
import { Table, Form, Input, Space } from "antd";

interface IPost {
id: number;
title: string;
label: string;
}

export default function PostList() {
const { tableProps } = useTable<IPost>();
const [editId, setEditId] = useState<number | null>(null);

const isEditing = (id: number) => id === editId;
return (
<List>
<Form>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column<IPost>
dataIndex="title"
title="Title"
/>
<Table.Column<IPost>
dataIndex="label"
title="Label"
render={(value, record) => {
if (isEditing(record.id)) {
return (
<Form.Item name="label" style={{ margin: 0 }}>
<Input defaultValue={value} />
</Form.Item>
);
}
return value;
}}
/>
<Table.Column<IPost>
title="Actions"
dataIndex="actions"
render={(_, record) => {
if (isEditing(record.id)) {
return (
<Space>
<SaveButton hideText size="small" />
<Button size="small" onClick={() => setEditId(null)}>
Cancel
</Button>
</Space>
);
}
return (
<EditButton
hideText
size="small"
onClick={() => setEditId(record.id)}
/>
);
}}
/>
</Table>
</Form>
</List>
);
}
import React, { useState } from "react";
import { List, useTable, EditButton, SaveButton, Button } from "@refinedev/antd";
import { Table, Form, Input, Space } from "antd";

interface IPost {
id: number;
title: string;
label: string;
}

export default function PostList() {
const { tableProps } = useTable<IPost>();
const [editId, setEditId] = useState<number | null>(null);

const isEditing = (id: number) => id === editId;
return (
<List>
<Form>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column<IPost>
dataIndex="title"
title="Title"
/>
<Table.Column<IPost>
dataIndex="label"
title="Label"
render={(value, record) => {
if (isEditing(record.id)) {
return (
<Form.Item name="label" style={{ margin: 0 }}>
<Input defaultValue={value} />
</Form.Item>
);
}
return value;
}}
/>
<Table.Column<IPost>
title="Actions"
dataIndex="actions"
render={(_, record) => {
if (isEditing(record.id)) {
return (
<Space>
<SaveButton hideText size="small" />
<Button size="small" onClick={() => setEditId(null)}>
Cancel
</Button>
</Space>
);
}
return (
<EditButton
hideText
size="small"
onClick={() => setEditId(record.id)}
/>
);
}}
/>
</Table>
</Form>
</List>
);
}
In this example: 1. We use the useTable hook to get the table properties. 2. We maintain an editId state to track which row is currently being edited. 3. We conditionally render an Input field inside the label column if the row is in editing mode. 4. We provide EditButton and SaveButton components to toggle between view and edit modes. This approach allows you to have a form input inside a table cell for each row, specifically for the label field. For more details, you can refer to the documentation on useEditableTable (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-editable-table/#usage) and the blog post on creating dynamic forms (https://refine.dev/blog/react-crud-app-with-dynamic-form-ant-design/#building-the-edit-page). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@490961337896402944> kapa.ai is still learning and improving, please let us know how it did by reacting below
metropolitan-bronze
metropolitan-bronzeOP3mo ago
@kapa.ai does this work with multiple rows?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, the approach can be extended to work with multiple rows. You can manage the editing state for multiple rows by using a state object that keeps track of the editing status for each row. Here is an updated example that supports multiple rows being edited simultaneously:
import React, { useState } from "react";
import { List, useTable, EditButton, SaveButton, Button } from "@refinedev/antd";
import { Table, Form, Input, Space } from "antd";

interface IPost {
id: number;
title: string;
label: string;
}

export default function PostList() {
const { tableProps } = useTable<IPost>();
const [editingRows, setEditingRows] = useState<{ [key: number]: boolean }>({});

const isEditing = (id: number) => !!editingRows[id];

const toggleEdit = (id: number) => {
setEditingRows((prev) => ({ ...prev, [id]: !prev[id] }));
};
return (
<List>
<Form>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column<IPost>
dataIndex="title"
title="Title"
/>
<Table.Column<IPost>
dataIndex="label"
title="Label"
render={(value, record) => {
if (isEditing(record.id)) {
return (
<Form.Item name={`label-${record.id}`} style={{ margin: 0 }}>
<Input defaultValue={value} />
</Form.Item>
);
}
return value;
}}
/>
<Table.Column<IPost>
title="Actions"
dataIndex="actions"
render={(_, record) => {
if (isEditing(record.id)) {
return (
<Space>
<SaveButton hideText size="small" />
<Button size="small" onClick={() => toggleEdit(record.id)}>
Cancel
</Button>
</Space>
);
}
return (
<EditButton
hideText
size="small"
onClick={() => toggleEdit(record.id)}
/>
);
}}
/>
</Table>
</Form>
</List>
);
}
import React, { useState } from "react";
import { List, useTable, EditButton, SaveButton, Button } from "@refinedev/antd";
import { Table, Form, Input, Space } from "antd";

interface IPost {
id: number;
title: string;
label: string;
}

export default function PostList() {
const { tableProps } = useTable<IPost>();
const [editingRows, setEditingRows] = useState<{ [key: number]: boolean }>({});

const isEditing = (id: number) => !!editingRows[id];

const toggleEdit = (id: number) => {
setEditingRows((prev) => ({ ...prev, [id]: !prev[id] }));
};
return (
<List>
<Form>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column<IPost>
dataIndex="title"
title="Title"
/>
<Table.Column<IPost>
dataIndex="label"
title="Label"
render={(value, record) => {
if (isEditing(record.id)) {
return (
<Form.Item name={`label-${record.id}`} style={{ margin: 0 }}>
<Input defaultValue={value} />
</Form.Item>
);
}
return value;
}}
/>
<Table.Column<IPost>
title="Actions"
dataIndex="actions"
render={(_, record) => {
if (isEditing(record.id)) {
return (
<Space>
<SaveButton hideText size="small" />
<Button size="small" onClick={() => toggleEdit(record.id)}>
Cancel
</Button>
</Space>
);
}
return (
<EditButton
hideText
size="small"
onClick={() => toggleEdit(record.id)}
/>
);
}}
/>
</Table>
</Form>
</List>
);
}
In this example: 1. We use an editingRows state object to track the editing status of each row. 2. The isEditing function checks if a specific row is in editing mode. 3. The toggleEdit function toggles the editing state for a specific row. 4. The Form.Item component uses a unique name for each row's input field to avoid conflicts. This approach allows you to edit multiple rows simultaneously in the table. For more details, you can refer to the documentation on useEditableTable (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-editable-table/#usage) and the blog post on creating dynamic forms (https://refine.dev/blog/react-crud-app-with-dynamic-form-ant-design/#building-the-edit-page). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@490961337896402944> kapa.ai is still learning and improving, please let us know how it did by reacting below