Template and multilevel nesting in EJ2 TypeScript Context menu control
3 Jan 202514 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 { ContextMenu, ContextMenuModel } from '@syncfusion/ej2-navigations';
import { enableRipple, Browser, select } from '@syncfusion/ej2-base';
enableRipple(true);
//ContextMenu items definition
let 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"
},
];
let menuOptions: ContextMenuModel = {
target: '#contextmenutarget',
items: menuItems,
itemTemplate: "#cmenuTemplate",
beforeOpen: (args: { element: HTMLElement }) => {
if (args.element.classList.contains('e-ul')) {
args.element.classList.add('e-contextMenu-template')
}
}
};
let menuObj: ContextMenu = new ContextMenu(menuOptions, '#contextmenu');
if (Browser.isDevice) {
select('#contextmenutarget').textContent = 'Right-click or touch and hold to open the Context Menu and select the answer type';
menuObj.animationSettings.effect = 'ZoomIn';
} else {
select('#contextmenutarget').textContent = 'Right click/Touch hold to open the Context Menu and select the answer type';
menuObj.animationSettings.effect = 'SlideDown';
}
<!DOCTYPE html>
<html lang="en">
<head>
<title>Essential JS 2</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta name="description" content="Essential JS 2" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-base/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-lists/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-inputs/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-navigations/styles/material.css" rel="stylesheet" />
<!--style reference from app-->
<link href="styles.css" rel="stylesheet" />
<!--system js reference and configuration-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>LOADING....</div>
<div class="control-section">
<div class="contextmenu-control">
<div id='contextmenutarget'></div>
<ul id='contextmenu' class="e-contextMenu-template"></ul>
<script id="cmenuTemplate" type="text/x-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>
</script>
</div>
</div>
</body>
</html>
Customize the specific menu items
The ContextMenu items can be customized by using the beforeItemRender
event. The item render event
triggers while rendering each menu item. The event argument will be used to identify the menu item and customize 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 { ContextMenu, MenuEventArgs, MenuItemModel, ContextMenuModel } from '@syncfusion/ej2-navigations';
enableRipple(true);
// Initialize menu items.
let menuItems: MenuItemModel[] = [
{
text: 'Save as...'
},
{
text: 'View page source'
},
{
text: 'Inspect'
}];
// Initialize ContextMenu options.
let menuOptions: ContextMenuModel = {
target: '#target',
items: menuItems,
beforeItemRender: (args: MenuEventArgs) => {
// To render template in li.
let shortCutSpan: HTMLElement = createElement('span');
let text: string = args.item.text;
let shortCutText: string = 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');
}
};
// Initialize ContextMenu component.
let menuObj: ContextMenu = new ContextMenu(menuOptions, '#contextmenu');
<!DOCTYPE html>
<html lang="en">
<head>
<title>Essential JS 2</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta name="description" content="Essential JS 2" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-base/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-lists/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-inputs/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-navigations/styles/material.css" rel="stylesheet" />
<!--style reference from app-->
<link href="styles.css" rel="stylesheet" />
<!--system js reference and configuration-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>LOADING....</div>
<div id='container'>
<!--target element-->
<div id="target">Right click / Touch hold to open the ContextMenu</div>
<!--element which is going to render-->
<ul id="contextmenu"></ul>
</div>
</body>
</html>
To create span element,
createElement
utility function used fromej2-base
.
Multilevel nesting
The 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.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Essential JS 2</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta name="description" content="Essential JS 2" />
<meta name="author" content="Syncfusion" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-base/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-buttons/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-lists/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-inputs/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="https://cdn.syncfusion.com/ej2/28.1.33/ej2-navigations/styles/material.css" rel="stylesheet" />
<!--style reference from app-->
<link href="styles.css" rel="stylesheet" />
<!--system js reference and configuration-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
<script src="https://cdn.syncfusion.com/ej2/syncfusion-helper.js" type ="text/javascript"></script>
</head>
<body>
<div id='loader'>LOADING....</div>
<div id='container'>
<!--target element-->
<div id="target">Right click / Touch hold to open the ContextMenu</div>
<!--element which is going to render-->
<ul id="contextmenu"></ul>
</div>
</body>
</html>
To open sub menu items only on click,
showItemOnClick
property should be set astrue
.