- Item template
- Customize the specific menu items
- Multilevel nesting
- See Also
Contact Support
Template and multilevel nesting in React Context menu component
13 Dec 202424 minutes to read
Item template
The itemTemplate property in the ContextMenu component allows you to define custom templates for displaying menu items within the context menu. This feature is particularly useful when you want to customize the appearance or layout of the menu items beyond the default text-based list.
import { enableRipple, Browser } from '@syncfusion/ej2-base';
import { ContextMenuComponent, MenuEventArgs, MenuItemModel } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';
enableRipple(true);
function App() {
const template = "<div class='menu-wrapper'><span class='${iconCss} icon-right'></span><div class='text-content'><span class='text'>${answerType}</span><span class='description'>${description}</span></div></div>";
let content = Browser.isDevice ? 'Right-click or touch and hold to open the Context Menu and select the answer type' : 'Right click/Touch hold to open the Context Menu and select the answer type';
// ContextMenu items definition
const menuItems = [
{
answerType: 'Selection',
description: "Choose from options",
iconCss: 'e-icons e-list-unordered'
},
{
answerType: 'Yes / No',
description: "Select Yes or No",
iconCss: 'e-icons e-check-box',
},
{
answerType: 'Text',
description: "Type own answer",
iconCss: 'e-icons e-caption',
items: [
{
answerType: 'Single line',
description: "Type answer in a single line",
iconCss: 'e-icons e-text-form'
},
{
answerType: 'Multiple line',
description: "Type answer in multiple line",
iconCss: 'e-icons e-text-wrap'
}
]
},
{
answerType: 'None',
iconCss: 'e-icons e-mouse-pointer',
description: "No answer required"
},
];
const addTemplateClass = (args) => {
if (args.element.classList.contains('e-ul')) {
args.element.classList.add('e-contextMenu-template');
}
};
return (
<div className='control-pane'>
<div className='control-section'>
<div className='contextmenu-section'>
<div id='contextmenu-control'>
<div id="contextmenutarget">{content}</div>
<ContextMenuComponent
className="e-contextMenu-template"
target='#contextmenutarget'
items={menuItems}
itemTemplate={template}
beforeOpen={addTemplateClass}
/>
</div>
</div>
</div>
</div>
);
}
export default App;
ReactDom.render(<App />, document.getElementById('element'));
import { enableRipple, Browser } from '@syncfusion/ej2-base';
import { ContextMenuComponent, MenuEventArgs, MenuItemModel } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';
enableRipple(true);
function App() {
const template: string = "<div class='menu-wrapper'><span class='${iconCss} icon-right'></span><div class='text-content'><span class='text'>${answerType}</span><span class='description'>${description}</span></div></div>";
let content: string = Browser.isDevice ? 'Right-click or touch and hold to open the Context Menu and select the answer type' : 'Right click/Touch hold to open the Context Menu and select the answer type';
// ContextMenu items definition
const menuItems: any = [
{
answerType: 'Selection',
description: "Choose from options",
iconCss: 'e-icons e-list-unordered'
},
{
answerType: 'Yes / No',
description: "Select Yes or No",
iconCss: 'e-icons e-check-box',
},
{
answerType: 'Text',
description: "Type own answer",
iconCss: 'e-icons e-caption',
items: [
{
answerType: 'Single line',
description: "Type answer in a single line",
iconCss: 'e-icons e-text-form'
},
{
answerType: 'Multiple line',
description: "Type answer in multiple line",
iconCss: 'e-icons e-text-wrap'
}
]
},
{
answerType: 'None',
iconCss: 'e-icons e-mouse-pointer',
description: "No answer required"
},
];
const addTemplateClass = (args: MenuEventArgs) => {
if (args.element.classList.contains('e-ul')) {
args.element.classList.add('e-contextMenu-template');
}
};
return (
<div className='control-pane'>
<div className='control-section'>
<div className='contextmenu-section'>
<div id='contextmenu-control'>
<div id="contextmenutarget">{content}</div>
<ContextMenuComponent
className="e-contextMenu-template"
target='#contextmenutarget'
items={menuItems}
itemTemplate={template}
beforeOpen={addTemplateClass}
/>
</div>
</div>
</div>
</div>
);
}
export default App;
ReactDom.render(<App />, document.getElementById('element'));
Customize the specific menu items
The ContextMenu items can be customized using the beforeItemRender
property. The item render event triggers while rendering each menu item. The event argument will be used to identify the menu item and customized it based on the requirement. In the following sample, the menu item is rendered with keycode for specified action in ContextMenu using the template. Here, the keycode is specified for Save as, View page source, and Inspect in the right side corner of the menu items by adding span element in the beforeItemRender
event.
import { createElement, enableRipple } from '@syncfusion/ej2-base';
import { ContextMenuComponent } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';
enableRipple(true);
function App() {
let menuItems = [
{
text: 'Save as...'
},
{
text: 'View page source'
},
{
text: 'Inspect'
}
];
function itemBeforeEvent(args) {
const shortCutSpan = createElement('span');
const text = args.item.text;
const shortCutText = text === 'Save as...' ? 'Ctrl + S' : (text === 'View page source' ? 'Ctrl + U' : 'Ctrl + Shift + I');
shortCutSpan.textContent = shortCutText;
args.element.appendChild(shortCutSpan);
shortCutSpan.setAttribute('class', 'shortcut');
}
return (<div class="container">
<div id='target'>Right click / Touch hold to open the ContextMenu</div>
<ContextMenuComponent id='contextmenu' target='#target' items={menuItems} beforeItemRender={itemBeforeEvent}/>
</div>);
}
export default App;
ReactDom.render(<App />, document.getElementById('element'));
import { createElement, enableRipple } from '@syncfusion/ej2-base';
import { ContextMenuComponent, MenuEventArgs, MenuItemModel } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';
enableRipple(true);
function App() {
let menuItems: MenuItemModel[] = [
{
text: 'Save as...'
},
{
text: 'View page source'
},
{
text: 'Inspect'
}];
function itemBeforeEvent(args: MenuEventArgs) {
const shortCutSpan = createElement('span');
const text = args.item.text;
const shortCutText = text === 'Save as...' ? 'Ctrl + S' : (text === 'View page source' ? 'Ctrl + U' : 'Ctrl + Shift + I');
shortCutSpan.textContent = shortCutText;
args.element.appendChild(shortCutSpan);
shortCutSpan.setAttribute('class','shortcut');
}
return (
<div class="container">
<div id='target'>Right click / Touch hold to open the ContextMenu</div>
<ContextMenuComponent id='contextmenu' target='#target'
items={menuItems} beforeItemRender={itemBeforeEvent}/>
</div>
);
}
export default App;
ReactDom.render(<App />,document.getElementById('element'));
To create span element,
createElement
util function used fromej2-base
.
Multilevel nesting
Multiple level nesting supports in ContextMenu. It can be achieved by mapping the items
property inside the parent menuItems
. In the below sample, three level nesting of ContextMenu is provided.
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { ContextMenuComponent } from '@syncfusion/ej2-react-navigations';
import { enableRipple } from '@syncfusion/ej2-base';
enableRipple(true);
function App() {
let menuItems = [
{
text: 'Show All Bookmarks'
},
{
text: 'Bookmarks Toolbar',
items: [
{
text: 'Most Visited',
items: [
{
text: 'Google'
},
{
text: 'Gmail'
}
]
},
{
text: 'Recently Added'
}
]
}
];
return (<div class="container">
<div id='target'>Right click / Touch hold to open the ContextMenu</div>
<ContextMenuComponent id='contextmenu' target='#target' items={menuItems}> </ContextMenuComponent>
</div>);
}
export default App;
ReactDom.render(<App />, document.getElementById('element'));
import * as React from 'react';
import * as ReactDom from 'react-dom';
import { ContextMenuComponent, MenuItemModel } from '@syncfusion/ej2-react-navigations';
import { enableRipple } from '@syncfusion/ej2-base';
enableRipple(true);
function App() {
let menuItems: MenuItemModel[] = [
{
text: 'Show All Bookmarks'
},
{
text: 'Bookmarks Toolbar',
items: [
{
text: 'Most Visited',
items: [
{
text: 'Google'
},
{
text: 'Gmail'
}
]
},
{
text: 'Recently Added'
}
]
}];
return (
<div class="container">
<div id='target'>Right click / Touch hold to open the ContextMenu</div>
<ContextMenuComponent id='contextmenu' target='#target'
items={menuItems}> </ContextMenuComponent>
</div>
);
}
export default App;
ReactDom.render(<App />,document.getElementById('element'));
To open sub menu items only on click,
showItemOnClick
property should be set astrue
.