Antd table with interfaces

Can you provide an example of a fully typed Antd table that includes at least one data relationship (e.g., category id to category name)
8 Replies
kapa.ai
kapa.ai3mo ago
Hi @Nitai. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- Sure! Below is an example of a fully typed Ant Design table using Refine that includes a data relationship between products and categories. This example demonstrates how to use the useTable and useMany hooks to handle relational data.
import { useTable, List, TextField } from "@refinedev/antd";
import { useMany } from "@refinedev/core";
import { Table } from "antd";

interface ICategory {
id: number;
title: string;
}

interface IProduct {
id: string;
name: string;
price: number;
category: { id: number };
}

export const ProductList: React.FC = (props) => {
const { tableProps } = useTable<IProduct>();

const categoryIds = tableProps?.dataSource?.map((item) => item.category.id) ?? [];

const { data: categoriesData, isLoading } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

return (
<List {...props}>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="name" title="Name" />
<Table.Column dataIndex="price" title="Price" />
<Table.Column
dataIndex={["category", "id"]}
title="Category"
render={(value: number) => {
if (isLoading) {
return <TextField value="Loading..." />;
}
return (
<TextField
strong
value={categoriesData?.data.find((item) => item.id === value)?.title}
/>
);
}}
/>
</Table>
</List>
);
};
import { useTable, List, TextField } from "@refinedev/antd";
import { useMany } from "@refinedev/core";
import { Table } from "antd";

interface ICategory {
id: number;
title: string;
}

interface IProduct {
id: string;
name: string;
price: number;
category: { id: number };
}

export const ProductList: React.FC = (props) => {
const { tableProps } = useTable<IProduct>();

const categoryIds = tableProps?.dataSource?.map((item) => item.category.id) ?? [];

const { data: categoriesData, isLoading } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

return (
<List {...props}>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="name" title="Name" />
<Table.Column dataIndex="price" title="Price" />
<Table.Column
dataIndex={["category", "id"]}
title="Category"
render={(value: number) => {
if (isLoading) {
return <TextField value="Loading..." />;
}
return (
<TextField
strong
value={categoriesData?.data.find((item) => item.id === value)?.title}
/>
);
}}
/>
</Table>
</List>
);
};
In this example: - The useTable hook is used to manage the table's state and properties. - The useMany hook is used to fetch the related category data based on the category IDs present in the products. - The Table.Column component is used to define the columns of the table, including a column that displays the category name by mapping the category ID to the category title. For more information, you can refer to the useTable documentation (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/) and the TextField component documentation (https://refine.dev/docs/ui-integrations/ant-design/components/fields/text-field/#usage). This should give you a good starting point for creating a fully typed Ant Design table with relational data using Refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@1091820430047838349> kapa.ai is still learning and improving, please let us know how it did by reacting below
multiple-amethyst
multiple-amethyst3mo ago
@kapa.ai The Table and Table.Column components do not offer type hints by default but they seem to take type arguments. Can you repeat the example ensuring that the returned Table and Table.Column components are fully typed?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Sure! Below is an example of a fully typed Ant Design table using Refine that includes a data relationship between products and categories. This example ensures that the Table and Table.Column components are fully typed.
import { useTable, List, TextField } from "@refinedev/antd";
import { useMany } from "@refinedev/core";
import { Table } from "antd";

interface ICategory {
id: number;
title: string;
}

interface IProduct {
id: string;
name: string;
price: number;
category: { id: number };
}

export const ProductList: React.FC = (props) => {
const { tableProps } = useTable<IProduct>();

const categoryIds = tableProps?.dataSource?.map((item) => item.category.id) ?? [];

const { data: categoriesData, isLoading } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

return (
<List {...props}>
<Table<IProduct> {...tableProps} rowKey="id">
<Table.Column<IProduct> dataIndex="id" title="ID" />
<Table.Column<IProduct> dataIndex="name" title="Name" />
<Table.Column<IProduct> dataIndex="price" title="Price" />
<Table.Column<IProduct>
dataIndex={["category", "id"]}
title="Category"
render={(value: number) => {
if (isLoading) {
return <TextField value="Loading..." />;
}
return (
<TextField
strong
value={categoriesData?.data.find((item) => item.id === value)?.title}
/>
);
}}
/>
</Table>
</List>
);
};
import { useTable, List, TextField } from "@refinedev/antd";
import { useMany } from "@refinedev/core";
import { Table } from "antd";

interface ICategory {
id: number;
title: string;
}

interface IProduct {
id: string;
name: string;
price: number;
category: { id: number };
}

export const ProductList: React.FC = (props) => {
const { tableProps } = useTable<IProduct>();

const categoryIds = tableProps?.dataSource?.map((item) => item.category.id) ?? [];

const { data: categoriesData, isLoading } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

return (
<List {...props}>
<Table<IProduct> {...tableProps} rowKey="id">
<Table.Column<IProduct> dataIndex="id" title="ID" />
<Table.Column<IProduct> dataIndex="name" title="Name" />
<Table.Column<IProduct> dataIndex="price" title="Price" />
<Table.Column<IProduct>
dataIndex={["category", "id"]}
title="Category"
render={(value: number) => {
if (isLoading) {
return <TextField value="Loading..." />;
}
return (
<TextField
strong
value={categoriesData?.data.find((item) => item.id === value)?.title}
/>
);
}}
/>
</Table>
</List>
);
};
In this example: - The useTable hook is used to manage the table's state and properties. - The useMany hook is used to fetch the related category data based on the category IDs present in the products. - The Table<IProduct> and Table.Column<IProduct> components are typed to ensure type safety. For more information, you can refer to the useTable documentation (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/) and the TextField component documentation (https://refine.dev/docs/ui-integrations/ant-design/components/fields/text-field/#usage). This should give you a good starting point for creating a fully typed Ant Design table with relational data using Refine. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@1091820430047838349> kapa.ai is still learning and improving, please let us know how it did by reacting below
multiple-amethyst
multiple-amethyst3mo ago
@kapa.ai is it possible for the components to infer the types from the useTable hook without needing to explicitly pass a type argument to them?
kapa.ai
kapa.ai3mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, it is possible for the components to infer the types from the useTable hook without needing to explicitly pass a type argument to them. The useTable hook can provide the necessary type information, which can then be used by the Table and Table.Column components. Here is an example demonstrating this approach:
import { useTable, List, TextField } from "@refinedev/antd";
import { useMany } from "@refinedev/core";
import { Table } from "antd";

interface ICategory {
id: number;
title: string;
}

interface IProduct {
id: string;
name: string;
price: number;
category: { id: number };
}

export const ProductList: React.FC = (props) => {
const { tableProps } = useTable<IProduct>();

const categoryIds = tableProps?.dataSource?.map((item) => item.category.id) ?? [];

const { data: categoriesData, isLoading } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

return (
<List {...props}>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="name" title="Name" />
<Table.Column dataIndex="price" title="Price" />
<Table.Column
dataIndex={["category", "id"]}
title="Category"
render={(value: number) => {
if (isLoading) {
return <TextField value="Loading..." />;
}
return (
<TextField
strong
value={categoriesData?.data.find((item) => item.id === value)?.title}
/>
);
}}
/>
</Table>
</List>
);
};
import { useTable, List, TextField } from "@refinedev/antd";
import { useMany } from "@refinedev/core";
import { Table } from "antd";

interface ICategory {
id: number;
title: string;
}

interface IProduct {
id: string;
name: string;
price: number;
category: { id: number };
}

export const ProductList: React.FC = (props) => {
const { tableProps } = useTable<IProduct>();

const categoryIds = tableProps?.dataSource?.map((item) => item.category.id) ?? [];

const { data: categoriesData, isLoading } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

return (
<List {...props}>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="name" title="Name" />
<Table.Column dataIndex="price" title="Price" />
<Table.Column
dataIndex={["category", "id"]}
title="Category"
render={(value: number) => {
if (isLoading) {
return <TextField value="Loading..." />;
}
return (
<TextField
strong
value={categoriesData?.data.find((item) => item.id === value)?.title}
/>
);
}}
/>
</Table>
</List>
);
};
In this example: - The useTable hook is used to manage the table's state and properties, and it provides type information for IProduct. - The Table and Table.Column components can infer the types from the tableProps provided by the useTable hook, eliminating the need to explicitly pass type arguments. For more information, you can refer to the useTable documentation (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-table/) and the TextField component documentation (https://refine.dev/docs/ui-integrations/ant-design/components/fields/text-field/#usage). This approach ensures that the components are fully typed without needing to explicitly pass type arguments, leveraging the type inference capabilities of TypeScript. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3mo ago
<@1091820430047838349> kapa.ai is still learning and improving, please let us know how it did by reacting below