documentation/versioned_docs/version-3.xx.xx/api-reference/antd/hooks/table/useEditableTable.md
import LivePreview from "./_partial-use-editable-table-live-preview.md";
useEditeableTable allows you to implement the edit feature on the <Table> with ease. Return properties that can be used on Ant Desing's <Table> and <Form> components.
:::info
useEditeableTable hook is extended from useTable hook from the @pankod/refine-antd package. This means that you can use all the features of useTable hook.
:::
Here is an example of how to use useEditableTable hook. We will explain in detail the usage of the hook in the following sections:
Let's say that we want to make the Post data where we show the id and title values a listing page:
This time, to add the edit feature, we have to cover the <Table> component with a <Form> component and pass the properties coming from useEditableTable to the corresponding components:
import {
List,
Table,
useEditableTable,
Form,
TextField,
} from "@pankod/refine-antd";
export const PostList: React.FC = () => {
// highlight-next-line
const { tableProps, formProps } = useEditableTable<IPost>();
return (
<List>
// highlight-start
<Form {...formProps}>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="title" title="Title" />
</Table>
</Form>
// highlight-end
</List>
);
};
interface IPost {
id: number;
title: string;
}
Now lets add a column for edit buttons:
import {
List,
Table,
Form,
// highlight-start
Space,
Button,
SaveButton,
EditButton,
// highlight-end
useEditableTable,
} from "@pankod/refine-antd";
export const PostList: React.FC = () => {
const {
tableProps,
formProps,
isEditing,
// highlight-start
saveButtonProps,
cancelButtonProps,
editButtonProps,
// highlight-end
} = useEditableTable<IPost>();
return (
<List>
<Form {...formProps}>
<Table {...tableProps} rowKey="id">
<Table.Column key="id" dataIndex="id" title="ID" />
<Table.Column key="title" dataIndex="title" title="Title" />
<Table.Column<IPost>
title="Actions"
dataIndex="actions"
key="actions"
// highlight-start
render={(_text, record) => {
if (isEditing(record.id)) {
return (
<Space>
<SaveButton {...saveButtonProps} size="small" />
<Button {...cancelButtonProps} size="small">
Cancel
</Button>
</Space>
);
}
return (
<Space>
<EditButton {...editButtonProps(record.id)} size="small" />
</Space>
);
}}
// highlight-end
/>
</Table>
</Form>
</List>
);
};
:::tip
isEditing function that returns from useEditableTable lets us check whether a line is currently in edit mode or not.
:::
For now, our post is not editable yet. If a post is being edited, we must show editable columns inside a <Form.Item> using conditional rendering:
import {
List,
Table,
Form,
Space,
Button,
SaveButton,
EditButton,
// highlight-start
Input,
TextField,
// highlight-end
useEditableTable,
} from "@pankod/refine-antd";
export const PostList: React.FC = () => {
const {
tableProps,
formProps,
isEditing,
saveButtonProps,
cancelButtonProps,
editButtonProps,
} = useEditableTable<IPost>();
return (
<List>
<Form {...formProps}>
<Table {...tableProps} rowKey="id">
<Table.Column key="id" dataIndex="id" title="ID" />
<Table.Column<IPost>
key="title"
dataIndex="title"
title="Title"
// highlight-start
render={(value, record) => {
if (isEditing(record.id)) {
return (
<Form.Item name="title" style={{ margin: 0 }}>
<Input />
</Form.Item>
);
}
return <TextField value={value} />;
}}
// highlight-end
/>
<Table.Column<IPost>
title="Actions"
dataIndex="actions"
key="actions"
render={(_text, record) => {
if (isEditing(record.id)) {
return (
<Space>
<SaveButton {...saveButtonProps} size="small" />
<Button {...cancelButtonProps} size="small">
Cancel
</Button>
</Space>
);
}
return (
<Space>
<EditButton {...editButtonProps(record.id)} size="small" />
</Space>
);
}}
/>
</Table>
</Form>
</List>
);
};
With this, when a user clicks on the edit button, isEditing(lineId) will turn true for the relevant line. This will also cause <TextInput> to show up on the line that's being edited. When the editing is finished, a new value can be saved by clicking <SaveButton>.
:::tip
By giving the <Table.Column> component a unique render property, you can render the value in that column however you want.
Refer to <Table.Column> documentation for more information.
:::
A line with the id value can be put to edit mode programmatically by using the setId function that returns from useEditableTable.
The onRow property of the <Table> component can be used to put a line to editing mode when it's clicked on. The function given to the onRow property is called every time one of these lines is clicked on, with the information of which line was clicked on.
We can use setId to put a line to edit mode whenever it's clicked on.
import {
List,
Table,
Form,
Input,
TextField,
useEditableTable,
} from "@pankod/refine-antd";
export const PostList: React.FC = () => {
// highlight-start
const { tableProps, formProps, isEditing, setId } = useEditableTable<IPost>();
// highlight-end
return (
<List>
<Form {...formProps}>
<Table
{...tableProps}
key="id"
// highlight-start
onRow={(record) => ({
onClick: (event: any) => {
if (event.target.nodeName === "TD") {
setId && setId(record.id);
}
},
})}
// highlight-end
>
<Table.Column key="id" dataIndex="id" title="ID" />
<Table.Column<IPost>
key="title"
dataIndex="title"
title="Title"
render={(value, data: any) => {
if (isEditing(data.id)) {
return (
<Form.Item name="title" style={{ margin: 0 }}>
<Input />
</Form.Item>
);
}
return <TextField value={value} />;
}}
/>
</Table>
</Form>
</List>
);
};
:::tip
All useForm and useTable properties are available in useEditableTable. You can read the documentation of useForm and useTable for more information.
:::
:::tip
All useForm and useTable return values are available in useEditableTable. You can read the documentation of useForm and useTable for more information.
:::
cancelButtonPropsReturns the props for needed by the <EditButton>.
By default, onClick function is overridden by useEditableTable. When is triggered it will call useForm's setId function with undefined.
cancelButtonProps: () => ButtonProps;
editButtonPropsTakes id as a parameter and returns the props needed by the <EditButton>.
By default, onClick function is overridden by useEditableTable. When is triggered it will call useForm's setId function with the given id.
editButtonProps: (id: BaseKey) => ButtonProps;
Returns a function that takes an id as a parameter and returns the props for the edit button.
isEditingisEditing: (id: BaseKey) => boolean;
Takes a id as a parameter and returns true if the given BaseKey is equal to the selected useForm's id.
| Property | Desription | Type | Default |
|---|---|---|---|
| TData | Result data of the query. Extends BaseRecord | BaseRecord | BaseRecord |
| TError | Custom error object that extends HttpError | HttpError | HttpError |
| TVariables | Values for params | {} | |
| TSearchVariables | Values for search params | {} |
| Property | Description | Type |
|---|---|---|
| searchFormProps | Ant Design <Form> props | FormProps<TSearchVariables> |
| tableProps | Ant Design <Table> props | TableProps<TData> |
| tableQueryResult | Result of the react-query's useQuery | QueryObserverResult<{`` data: TData[];`` total: number; },`` TError> |
| sorter | Current sorting state | CrudSorting |
| filters | Current filters state | CrudFilters |
| form | Ant Design <Form> instance | FormInstance |
| formProps | Ant Design <Form> props | FormProps |
| saveButtonProps | Props for a submit button | { disabled: boolean; onClick: () => void; } |
| cancelButtonProps | Props for a cancel button | { onClick: () => void; } |
| editButtonProps | Props for an edit button | { onClick: () => void; } |
| queryResult | Result of the query of a record | QueryObserverResult<T> |
| mutationResult | Result of the mutation triggered by submitting the form | UseMutationResult<T> |
| formLoading | Loading state of form request | boolean |
| id | Record id for edit action | BaseKey |
| setId | id setter | Dispatch<SetStateAction< BaseKey | undefined>> |
| isEditing | Check if is editing | (id: BaseKey) => boolean |