like-gold
like-gold9mo ago

How do you conventionally build a custom

How do you conventionally build a custom menu on Sider (with CanAccess)? If using ITreeMenu default of Refine, you can't add "create" menu item in. If I'm using AntD Menu Items, it lacks lots of functionalities comparing to Refine. What should I do?
9 Replies
kapa.ai
kapa.ai9mo ago
Hi @Batu. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
fair-rose
fair-rose9mo ago
Hello @lukevo. You can swizzle these components for your custom needs, or you can modify render prop of Sider component. Check our documentation here: https://refine.dev/docs/api-reference/antd/components/antd-themed-layout/#sider-props
| refine
component from refine, defines the overall structure and layout of a web page.
kapa.ai
kapa.ai9mo ago
Sorry @Batu, I seem to be having a bit of trouble. Don't worry though, I've pinged my supprt and they will try to fix me up! :technologist: Perhaps try again in 15mins?
extended-salmon
extended-salmon9mo ago
@kapa.ai @Batu Apparently Refine resource doesn't design to automatically add "create" action resource into Sider Menu item, only "list". I have already tried custom render for the Sider but then it will missed lots of already made functionalities comparing to auto generated menu items using resource props of <Refine>. What's the best way for this?
kapa.ai
kapa.ai9mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- You're correct that by default, the Refine framework only adds the "list" action of a resource to the Sider menu. However, you can customize the Sider component to include a "create" action or any other custom actions. There are two main ways to add an item to the Sider component: 1. Using the resources property on the <Refine> component: This is the simplest way. The <Sider> component shows the resources whose list property is set. So, you can have an extra navigation link by adding a resource with the list attribute. Here is an example:
import { Refine } from "@refinedev/core";

<Refine
...
resources={[
{
name: "dashboard",
list: "/",
meta: {
label: "Dashboard",
icon: "🏠",
},
},
]}
/>;
import { Refine } from "@refinedev/core";

<Refine
...
resources={[
{
name: "dashboard",
list: "/",
meta: {
label: "Dashboard",
icon: "🏠",
},
},
]}
/>;
Source (https://refine.dev/docs/faq/) 2. Using the render property of the <Sider> component: This method gives you more flexibility. The render property is a function that receives an object with the items and logout properties. The items property is the list of navigation items and the logout property is the logout button. Here is an example:
import { Layout, Sider } from "@refinedev/antd";

const CustomSider = () => {
return (
<Sider
render={({ items, logout }) => {
return (
<>
<a href="<https://refine.dev/">👋> Navigation Link</a>
{items}
{logout}
</>
);
}}
/>
);
};
import { Layout, Sider } from "@refinedev/antd";

const CustomSider = () => {
return (
<Sider
render={({ items, logout }) => {
return (
<>
<a href="<https://refine.dev/">👋> Navigation Link</a>
{items}
{logout}
</>
);
}}
/>
);
};
Source (https://refine.dev/docs/faq/) In your case, you can use the render property to add a "create" action link to the Sider. However, as you mentioned, this might require some additional work to match the look and feel of the auto-generated menu items. For the "create" action, you can use the create property of the resource configuration in the <Refine> component. The value assigned to the create will be treated as the create action path for the resource and the navigation operations will be performed on this path. Source (https://refine.dev/docs/api-reference/core/components/refine-config/#create) Remember to adjust the code according to your needs. For instance, you might want to style the new navigation link to make it look like the other items, or add some logic to only show it to certain users. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai9mo ago
<@582491401715974144> kapa.ai is still learning and improving, please let us know how it did by reacting below
extended-salmon
extended-salmon9mo ago
Can I modify useMenu some how to include "create" item in the "menuItems"? const prepareItem = React.useCallback( (item: FlatTreeItem): TreeMenuItem | undefined => { if (item?.meta?.hide ?? item?.options?.hide) return undefined; if (!item?.list && item.children.length === 0) return undefined; const composed = item.list ? getToPath({ resource: item, action: "list", legacy: routerType === "legacy", meta, }) : undefined; if ( hideOnMissingParameter && composed && composed.match(/(/|^):(.+?)(/|$){1}/) ) return undefined; return { ...item, route: composed, icon: pickNotDeprecated( item.meta?.icon, item.options?.icon, item.icon, ), label: pickNotDeprecated( item?.meta?.label, item?.options?.label, ) ?? translate( ${item.name}.${item.name}, getFriendlyName(item.name, "plural"), ), }; }, [routerType, meta, translate, hideOnMissingParameter], ); @kapa.ai
kapa.ai
kapa.ai9mo ago
Let me check the knowledge base for you. One moment! :books: ---------------------- The useMenu hook in Refine is used to generate menu items based on the resources defined in the Refine component. By default, it only includes the "list" action for each resource. Modifying the useMenu hook directly is not recommended as it's part of the Refine library and any changes might be overwritten when you update the library. However, you can create a wrapper around the useMenu hook to add the "create" action to the menu items. Here's a basic example of how you might do this:
import { useMenu } from "@refinedev/core";

const useCustomMenu = () => {
const menu = useMenu();

const customMenuItems = menu.menuItems.map(item => ({
...item,
children: [
...item.children,
{
name: 'Create',
key: `${item.key}/create`,
route: `${item.route}/create`,
children: [],
},
],
}));

return {
...menu,
menuItems: customMenuItems,
};
};
import { useMenu } from "@refinedev/core";

const useCustomMenu = () => {
const menu = useMenu();

const customMenuItems = menu.menuItems.map(item => ({
...item,
children: [
...item.children,
{
name: 'Create',
key: `${item.key}/create`,
route: `${item.route}/create`,
children: [],
},
],
}));

return {
...menu,
menuItems: customMenuItems,
};
};
In this example, the useCustomMenu hook uses the useMenu hook to get the default menu items, then adds a "Create" submenu item to each menu item. The route for the "Create" item is the route of the parent item with "/create" appended to it. Please note that this is a basic example and might not cover all your needs. You might need to adjust it according to your application's requirements. For instance, you might want to only add the "Create" item for certain resources, or only show it to certain users. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai9mo ago
<@582491401715974144> kapa.ai is still learning and improving, please let us know how it did by reacting below