absent-sapphire
absent-sapphire4mo ago

sub resource on show page

I have a resource called order, in the backend an order has a line item, however this is not a refine resource in the frontend. How can I show a list/table of line items (specified for that order) when looking at the show page of an order? So for example when I look at order 5, it shows a list/table with line items that part of order 5. the backend url (simple rest) is /orders/:orderId/items/
14 Replies
kapa.ai
kapa.ai4mo 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: ---------------------- You can achieve this by using the useGetList hook from Refine. This hook allows you to fetch a list of resources from your API. In your case, you can use it to fetch the line items for a specific order. Here's a basic example of how you can use it:
import { useShow, useGetList } from "@refinedev/core";
import { Show } from "@refinedev/mui";

const OrderShow = () => {
const { queryResult } = useShow();
const { data, isLoading } = queryResult;
const orderId = data?.data?.id;

const {
data: lineItemsData,
isLoading: lineItemsLoading,
} = useGetList({
resource: `orders/${orderId}/items`,
queryOptions: {
enabled: !!orderId,
},
});

return (
<Show isLoading={isLoading}>
{/* Display order details here */}
{lineItemsLoading ? (
"Loading line items..."
) : (
<div>
{/* Display line items here */}
{lineItemsData?.data.map((item) => (
<div key={item.id}>{/* Display item details here */}</div>
))}
</div>
)}
</Show>
);
};
import { useShow, useGetList } from "@refinedev/core";
import { Show } from "@refinedev/mui";

const OrderShow = () => {
const { queryResult } = useShow();
const { data, isLoading } = queryResult;
const orderId = data?.data?.id;

const {
data: lineItemsData,
isLoading: lineItemsLoading,
} = useGetList({
resource: `orders/${orderId}/items`,
queryOptions: {
enabled: !!orderId,
},
});

return (
<Show isLoading={isLoading}>
{/* Display order details here */}
{lineItemsLoading ? (
"Loading line items..."
) : (
<div>
{/* Display line items here */}
{lineItemsData?.data.map((item) => (
<div key={item.id}>{/* Display item details here */}</div>
))}
</div>
)}
</Show>
);
};
In this example, we're using the useShow hook to fetch the details of the order. We then use the useGetList hook to fetch the line items for that order. The resource prop for useGetList is set to orders/${orderId}/items, which corresponds to the URL you provided. Please note that you'll need to replace the comments with the actual code to display the order and line item details. For more information, you can refer to the documentation for the useShow (https://refine.dev/docs/guides-concepts/routing#relationship-between-resources-and-routes-) and useGetList (https://refine.dev/docs/guides-concepts/general-concepts#ui-integrations-) hooks. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@490961337896402944> kapa.ai is still learning and improving, please let us know how it did by reacting below
absent-sapphire
absent-sapphire4mo ago
@kapa.ai can I use an actual list or antdesign table for these line items, instead of a simple div. Also please replace the comments with an actual example
kapa.ai
kapa.ai4mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can use an Ant Design Table to display the line items. Here's an example of how you can do it:
import { useShow, useGetList } from "@pankod/refine";
import { Show, Table } from "@pankod/refine";
import { Table as AntTable } from "antd";

const OrderShow = () => {
const { queryResult } = useShow();
const { data, isLoading } = queryResult;
const orderId = data?.data?.id;

const {
data: lineItemsData,
isLoading: lineItemsLoading,
} = useGetList({
resource: `orders/${orderId}/items`,
queryOptions: {
enabled: !!orderId,
},
});

const columns = [
{
title: 'Item Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Quantity',
dataIndex: 'quantity',
key: 'quantity',
},
// Add more columns as needed
];

return (
<Show isLoading={isLoading}>
{/* Display order details here */}
{lineItemsLoading ? (
"Loading line items..."
) : (
<Table dataSource={lineItemsData?.data} rowKey="id">
<AntTable columns={columns} />
</Table>
)}
</Show>
);
};
import { useShow, useGetList } from "@pankod/refine";
import { Show, Table } from "@pankod/refine";
import { Table as AntTable } from "antd";

const OrderShow = () => {
const { queryResult } = useShow();
const { data, isLoading } = queryResult;
const orderId = data?.data?.id;

const {
data: lineItemsData,
isLoading: lineItemsLoading,
} = useGetList({
resource: `orders/${orderId}/items`,
queryOptions: {
enabled: !!orderId,
},
});

const columns = [
{
title: 'Item Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Quantity',
dataIndex: 'quantity',
key: 'quantity',
},
// Add more columns as needed
];

return (
<Show isLoading={isLoading}>
{/* Display order details here */}
{lineItemsLoading ? (
"Loading line items..."
) : (
<Table dataSource={lineItemsData?.data} rowKey="id">
<AntTable columns={columns} />
</Table>
)}
</Show>
);
};
In this example, we're using the Table component from Refine and the Table component from Ant Design to display the line items. The dataSource prop for the Refine Table is set to lineItemsData?.data, which is the data fetched by the useGetList hook. The columns prop for the Ant Design Table is set to an array of objects, each representing a column in the table. Please note that you'll need to replace the columns array with the actual columns for your line items. For more information, you can refer to the documentation for the Table (https://refine.dev/docs/api-references/components/table) component from Refine and the Table (https://ant.design/components/table/) component from Ant Design. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@490961337896402944> kapa.ai is still learning and improving, please let us know how it did by reacting below
absent-sapphire
absent-sapphire4mo ago
@kapa.ai can I use an actual refine List component so it has pagination and stuff?
kapa.ai
kapa.ai4mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can use the List component from Refine to display the line items with built-in pagination. However, the List component is designed to work with top-level resources, and it might not work directly with nested resources like your line items. A workaround is to create a custom component that uses the useGetList hook and the Table component from Ant Design. You can then manually implement pagination using the pagination prop of the Table component. Here's an example:
import { useShow, useGetList } from "@pankod/refine";
import { Show } from "@pankod/refine";
import { Table as AntTable } from "antd";

const OrderShow = () => {
const { queryResult } = useShow();
const { data, isLoading } = queryResult;
const orderId = data?.data?.id;

const {
data: lineItemsData,
isLoading: lineItemsLoading,
pageInfo,
setPage,
} = useGetList({
resource: `orders/${orderId}/items`,
queryOptions: {
enabled: !!orderId,
},
});

const columns = [
{
title: 'Item Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Quantity',
dataIndex: 'quantity',
key: 'quantity',
},
// Add more columns as needed
];
return (
<Show isLoading={isLoading}>
{/* Display order details here */}
{lineItemsLoading ? (
"Loading line items..."
) : (
<AntTable
dataSource={lineItemsData?.data}
columns={columns}
rowKey="id"
pagination={{
current: pageInfo.current,
pageSize: pageInfo.pageSize,
total: pageInfo.total,
onChange: (page) => setPage(page),
}}
/>
)}
</Show>
);
};
import { useShow, useGetList } from "@pankod/refine";
import { Show } from "@pankod/refine";
import { Table as AntTable } from "antd";

const OrderShow = () => {
const { queryResult } = useShow();
const { data, isLoading } = queryResult;
const orderId = data?.data?.id;

const {
data: lineItemsData,
isLoading: lineItemsLoading,
pageInfo,
setPage,
} = useGetList({
resource: `orders/${orderId}/items`,
queryOptions: {
enabled: !!orderId,
},
});

const columns = [
{
title: 'Item Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Quantity',
dataIndex: 'quantity',
key: 'quantity',
},
// Add more columns as needed
];
return (
<Show isLoading={isLoading}>
{/* Display order details here */}
{lineItemsLoading ? (
"Loading line items..."
) : (
<AntTable
dataSource={lineItemsData?.data}
columns={columns}
rowKey="id"
pagination={{
current: pageInfo.current,
pageSize: pageInfo.pageSize,
total: pageInfo.total,
onChange: (page) => setPage(page),
}}
/>
)}
</Show>
);
};
In this example, we're using the pageInfo and setPage returned by useGetList to control the pagination of the AntTable. The pagination prop of AntTable is set to an object that controls the current page, page size, total number of items, and the function to call when the page changes. Please note that this is a basic example and you might need to adjust it based on your actual API and data structure. For more information, you can refer to the documentation for the useGetList (https://refine.dev/docs/api-references/hooks/data/useGetList) hook and the Table (https://ant.design/components/table/) component from Ant Design. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@490961337896402944> kapa.ai is still learning and improving, please let us know how it did by reacting below
absent-sapphire
absent-sapphire4mo ago
@kapa.ai how do I use List?
kapa.ai
kapa.ai4mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The List component in Refine provides a layout to display a page. It does not contain any logic but adds extra functionalities like a create button or giving titles to the page. Here's an example of how you can use it with Ant Design:
import { useMany } from "@refinedev/core";
import { List, TextField, TagField, useTable } from "@refinedev/antd";
import { Table } from "antd";

const PostList: React.FC = () => {
const { tableProps } = useTable<IPost>({
syncWithLocation: true,
});

const categoryIds =
tableProps?.dataSource?.map((item) => item.category.id) ?? [];
const { data, isLoading } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="title" title="Title" />
<Table.Column
dataIndex={["category", "id"]}
title="Category"
render={(value) => {
if (isLoading) {
return <TextField value="Loading..." />;
}

return (
<TextField
value={data?.data.find((item) => item.id === value)?.title}
/>
);
}}
/>
<Table.Column
dataIndex="status"
title="Status"
render={(value: string) => <TagField value={value} />}
/>
</Table>
</List>
);
};
import { useMany } from "@refinedev/core";
import { List, TextField, TagField, useTable } from "@refinedev/antd";
import { Table } from "antd";

const PostList: React.FC = () => {
const { tableProps } = useTable<IPost>({
syncWithLocation: true,
});

const categoryIds =
tableProps?.dataSource?.map((item) => item.category.id) ?? [];
const { data, isLoading } = useMany<ICategory>({
resource: "categories",
ids: categoryIds,
queryOptions: {
enabled: categoryIds.length > 0,
},
});

return (
<List>
<Table {...tableProps} rowKey="id">
<Table.Column dataIndex="id" title="ID" />
<Table.Column dataIndex="title" title="Title" />
<Table.Column
dataIndex={["category", "id"]}
title="Category"
render={(value) => {
if (isLoading) {
return <TextField value="Loading..." />;
}

return (
<TextField
value={data?.data.find((item) => item.id === value)?.title}
/>
);
}}
/>
<Table.Column
dataIndex="status"
title="Status"
render={(value: string) => <TagField value={value} />}
/>
</Table>
</List>
);
};
In this example, the List component is used as a wrapper around the Table component. The List component does not require any props because Refine figures the resource name and title from the resources prop. For more information, you can refer to the Refine documentation (https://refine.dev/docs/ui-integrations/ant-design/components/basic-views/list) and this blog post (https://refine.dev/blog/refine-pixels-5#refine-ant-design-list--component). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4mo ago
<@490961337896402944> kapa.ai is still learning and improving, please let us know how it did by reacting below
absent-sapphire
absent-sapphire2mo ago
@kapa.ai can I use a custom url inside resource inside simpleList? I need to get the current business and then all the services, the backend url will look like this /business/{idThatIsCurrentlyShown}/services
kapa.ai
kapa.ai2mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- Yes, you can use a custom URL inside the resource prop of the useSimpleList hook. This allows you to specify a custom endpoint for fetching data. Here's an example of how you can achieve this:
import React from "react";
import { useSimpleList } from "@refinedev/antd";
import { List, Table } from "antd";

const BusinessServicesList = ({ businessId }) => {
const { tableQueryResult: servicesQueryResult } = useSimpleList({
resource: `business/${businessId}/services`,
});

const columns = [
{
title: 'Service Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Description',
dataIndex: 'description',
key: 'description',
},
// Add more columns as needed
];

return (
<List>
<Table
dataSource={servicesQueryResult.data?.data}
columns={columns}
rowKey="id"
loading={servicesQueryResult.isLoading}
/>
</List>
);
};

export default BusinessServicesList;
import React from "react";
import { useSimpleList } from "@refinedev/antd";
import { List, Table } from "antd";

const BusinessServicesList = ({ businessId }) => {
const { tableQueryResult: servicesQueryResult } = useSimpleList({
resource: `business/${businessId}/services`,
});

const columns = [
{
title: 'Service Name',
dataIndex: 'name',
key: 'name',
},
{
title: 'Description',
dataIndex: 'description',
key: 'description',
},
// Add more columns as needed
];

return (
<List>
<Table
dataSource={servicesQueryResult.data?.data}
columns={columns}
rowKey="id"
loading={servicesQueryResult.isLoading}
/>
</List>
);
};

export default BusinessServicesList;
In this example, the resource prop of the useSimpleList hook is set to business/${businessId}/services, which corresponds to your custom backend URL. The Table component from Ant Design is used to display the list of services. For more information, you can refer to the Refine documentation on useSimpleList (https://refine.dev/docs/ui-integrations/ant-design/hooks/use-simple-list#resource). ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai2mo ago
<@490961337896402944> kapa.ai is still learning and improving, please let us know how it did by reacting below