useEditableTable
useEditeableTable
allows you to implement the edit feature on the <Table>
with ease and returns properties that can be used on Ant Design's <Table>
and <Form>
components.
useEditeableTable
hook is extended from the useTable
hook from the @refinedev/antd
package. This means that you can use all the features of useTable
hook.
Usage
Here is an example of how to use useEditableTable
hook. We will explain the details of this example and hooks usage in the following sections.
Editing with buttons
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, useEditableTable, TextField } from "@refinedev/antd";
import { Table, Form } from "antd";
export const PostList: React.FC = () => {
const { tableProps, formProps } = useEditableTable<IPost>();
return (
<List>
<Form {...formProps}>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="title" title="Title" />
</Table>
</Form>
</List>
);
};
interface IPost {
id: number;
title: string;
}
Now lets add a column for edit buttons:
import {
List,
SaveButton,
EditButton,
useEditableTable,
} from "@refinedev/antd";
import {
Table,
Form,
Space,
Button,
} from "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 key="title" dataIndex="title" title="Title" />
<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>
);
};
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,
SaveButton,
EditButton,
TextField,
useEditableTable,
} from "@refinedev/antd";
import {
Table,
Form,
Space,
Button,
Input,
} from "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"
render={(value, record) => {
if (isEditing(record.id)) {
return (
<Form.Item name="title" style={{ margin: 0 }}>
<Input />
</Form.Item>
);
}
return <TextField value={value} />;
}}
/>
<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>
.
By giving the <Table.Column>
component a unique render
property, you can render the value in that column however you want.
For more information, refer to the <Table.Column>
documentation →
Editing by clicking to row
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, TextField, useEditableTable } from "@refinedev/antd";
import { Table, Form, Input } from "antd";
export const PostList: React.FC = () => {
const { tableProps, formProps, isEditing, setId } = useEditableTable<IPost>();
return (
<List>
<Form {...formProps}>
<Table
{...tableProps}
key="id"
onRow={(record) => ({
onClick: (event: any) => {
if (event.target.nodeName === "TD") {
setId && setId(record.id);
}
},
})}
>
<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>
);
};
Properties
All useForm
and useTable
properties are available in useEditableTable
. You can read the documentation of useForm
and useTable
for more information.
autoSubmitClose
autoSubmitClose
makes the table's row close after a successful submit. It is true
by default.
For this effect, useEditableTable
automatically calls the setId
function with undefined
after successful submit.
const editableTable = useEditableTable({
autoSubmitClose: false,
});
Return Values
All useForm
and useTable
return values are available in useEditableTable
. You can read the documentation of useForm
and useTable
for more information.
cancelButtonProps
cancelButtonProps
returns the props for needed by the <EditButton>
.
By default, the onClick
function is overridden by useEditableTable
. Which will call useForm's
setId
function with undefined
when called.
cancelButtonProps: () => ButtonProps;
editButtonProps
editButtonProps
takes id
as a parameter and returns the props needed by the <EditButton>
.
By default, the onClick
function is overridden by useEditableTable
. Which will call useForm's
setId
function with the given id
when called.
editButtonProps: (id: BaseKey) => ButtonProps;
It also returns a function that takes an id
as a parameter and returns the props for the edit button.
isEditing
isEditing: (id: BaseKey) => boolean;
Takes a id
as a parameter and returns true
if the given BaseKey
is equal to the selected useForm's
id
.
API
Properties
Property | Type | Description | Default |
---|---|---|---|
resource |
| Resource name for API data interactions | Resource name that it reads from route Resource name that it reads from route |
meta |
| Metadata query for dataProvider | |
metaData
|
| Metadata query for dataProvider | |
liveMode | Whether to update data automatically ("auto") or not ("manual") if a related live event is received. The "off" value is used to avoid creating a subscription. |
| |
liveParams | Params to pass to liveProvider's subscribe method if liveMode is enabled. |
| |
dataProviderName |
| If there is more than one | |
onLiveEvent | Callback to handle all related live events of this hook. |
| |
queryOptions |
| react-query's useQuery options react-query's useQuery options of useOne hook used while in edit mode. | |
overtimeOptions |
| ||
syncWithLocation |
| Sortings, filters, page index and records shown per page are tracked by browser history | Value set in Refine. If a custom resource is given, it will be |
onSearch |
| ||
initialCurrent
|
| Initial page index | 1 |
initialPageSize
|
| Initial number of items per page | 10 |
hasPagination
|
| Whether to use server side pagination or not. |
|
pagination |
| Configuration for pagination | |
initialSorter
|
| Initial sorter state | |
permanentSorter
|
| Default and unchangeable sorter state |
|
initialFilter
|
| Initial filter state | |
permanentFilter
|
| Default and unchangeable filter state |
|
defaultSetFilterBehavior
|
| Default behavior of the |
|
filters |
| Filter configs | |
sorters |
| Sort configs | |
id | Record id for fetching | Id that it reads from the URL | |
redirect |
| Page to redirect after a succesfull mutation |
|
queryMeta |
| Metadata to pass for the | |
mutationMeta |
| Metadata to pass for the mutation ( | |
mutationMode |
|
| |
onMutationSuccess |
| Called when a mutation is successful | |
onMutationError |
| Called when a mutation encounters an error | |
undoableTimeout |
| Duration to wait before executing mutations when |
|
invalidates |
| You can use it to manage the invalidations that will occur at the end of the mutation. |
|
createMutationOptions |
| react-query's useMutation options of useCreate hook used while submitting in create and clone modes. | |
updateMutationOptions |
| react-query's useMutation options of useUpdate hook used while submitting in edit mode. | |
optimisticUpdateMap |
| If you customize the | { list: true, many: true, detail: true, } |
successNotification |
| Success notification configuration to be displayed when the mutation is successful. | '"There was an error creating resource (status code: |
errorNotification |
| Error notification configuration to be displayed when the mutation fails. | '"There was an error creating resource (status code: |
action |
| Type of the form mode | Action that it reads from route otherwise "create" is used |
autoSave |
| ||
autoSubmitClose |
| When true, row will be closed after successful submit. |
|
Type Parameters
Property | Description | Type | Default |
---|---|---|---|
TQueryFnData | Result data returned by the query function. Extends BaseRecord | BaseRecord | BaseRecord |
TError | Custom error object that extends HttpError | HttpError | HttpError |
TVariables | Values for params | {} | |
TSearchVariables | Values for search params | {} | |
TData | Result data returned by the select function. Extends BaseRecord . If not specified, the value of TQueryFnData will be used as the default value. | BaseRecord | TQueryFnData |
Return values
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 |
Example
npm create refine-app@latest -- --example table-antd-use-editable-table