blueprint
blueprint copied to clipboard
How to pass custom props to ContextMenu2 content?
Environment
- Package version(s):
"@blueprintjs/core": "4.0.0-beta.11", "@blueprintjs/icons": "4.0.0-beta.6", "@blueprintjs/popover2": "^0.12.9", "@blueprintjs/select": "4.0.0-beta.11", - Operating System: MacOS 12.2
- Browser name and version: Firefox (latest), Chrome (latest)
Question
I'm creating a canvas-based PKM tool, and need to add a context menu to every item on the canvas. I've done this by wrapping all the elements in a single <ContextMenu2 /> with a content prop, and using the advanced rendering pattern to provide a custom wrapper for my layout.
<ContextMenu2
content={
<Menu>
<MenuItem
icon="send-to-graph"
// Need access to "block" prop
onClick={() => handleBlockClick(props.block)}
text="Add to canvas"
/>
<MenuItem
intent="danger"
icon="trash"
// Need access to "block" prop
onClick={() => props.handleBlockClick(props.block)}
text={`Delete ${props.block.__typename}`}
/>
</Menu>
}
>
{(ctxMenuProps) => (
<div
className={classNames('grid', ctxMenuProps.className)}
onContextMenu={ctxMenuProps.onContextMenu}
ref={ctxMenuProps.ref}
>
{blocks.map((block) => (
<Card
key={block.id}
interactive={false}
onClick={(e) => { ... }}
>
{ctxMenuProps.popover}
<div>
block content
</div>
</Card>
))}
</div>
)}
</ContextMenu2>
You'll notice the blocks.map() line, which renders the items on the canvas, each of which should have a context menu that passes a block prop to the content of the context menu. That way, when the context menu is opened for a block, I can click Delete block and have access to its ID in the <Menu />
Is this possible?
I was hoping I could do something similar to the advanced context menu render pattern:
<ContextMenu2
content={(ctxContentProps) => (
<Menu>
<MenuItem
icon="send-to-graph"
// Access my block prop which was put on the cloned ctxMenuProps.popover
onClick={() => handleBlockClick(ctxContentProps.block)}
text="Add to canvas"
/>
{/* other menu items */}
</Menu>
)}
>
{(ctxMenuProps) => (
<div
className={classNames('grid', ctxMenuProps.className)}
onContextMenu={ctxMenuProps.onContextMenu}
ref={ctxMenuProps.ref}
>
{blocks.map((block) =>
// Clone the popover element and pass the block prop
React.cloneElement(
ctxMenuProps.popover,
{ block: ctxMenuProps.popover }
// block content here
)
)}
</div>
)}
</ContextMenu2>;
Update: I was able to achieve this by adding a state value that is set within onContextMenu, and then used within the ContextMenu2 content prop. Still curious if there is a better way to do this though.