The submenu position can be changed by using the beforeOpen
event. Assign the top and left position where you want to open the submenu to the beforeOpen
event arguments args.top
and args.left
respectively.
In the below sample, the sub menu opens above the parent menu item.
import { closest, enableRipple } from '@syncfusion/ej2-base';
import { MenuComponent } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';
enableRipple(true);
class App extends React.Component {
constructor() {
super(...arguments);
// Menu items definition
this.menuItems = [
{
items: [
{ text: 'Open' },
{ text: 'Save' },
{ text: 'Exit' }
],
text: 'File'
},
{
items: [
{ text: 'Cut' },
{ text: 'Copy' },
{ text: 'Paste' }
],
text: 'Edit'
},
{
items: [
{ text: 'Toolbar' },
{ text: 'Sidebar' }
],
text: 'View'
},
{
items: [
{ text: 'Spelling & Grammar' },
{ text: 'Customize' },
{ text: 'Options' }
],
text: 'Tools'
},
{ text: 'Go' },
{ text: 'Help' }
];
}
onBeforeOpen(args) {
// Getting parent menu item element offset
const relativeOffset = closest(args.event.target, '.e-menu-item').getBoundingClientRect();
// Getting sub menu wrapper element using closest method
const subMenuEle = closest(args.element, '.e-menu-wrapper');
subMenuEle.style.display = 'block';
args.top = (relativeOffset.top - subMenuEle.getBoundingClientRect().height) + pageYOffset;
args.left = relativeOffset.left + pageXOffset;
subMenuEle.style.display = '';
}
render() {
return (<MenuComponent items={this.menuItems} beforeOpen={this.onBeforeOpen}/>);
}
}
ReactDom.render(<App />, document.getElementById('element'));
<!DOCTYPE html>
<html lang="en">
<head>
<title>Syncfusion React ContextMenu</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Essential JS 2 for React Components" />
<meta name="author" content="Syncfusion" />
<link href="//cdn.syncfusion.com/ej2/20.1.55/ej2-base/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/20.1.55/ej2-popups/styles/material.css" rel="stylesheet" />
<link href="//cdn.syncfusion.com/ej2/20.1.55/ej2-navigations/styles/material.css" rel="stylesheet" />
<link href="index.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
<script src="systemjs.config.js"></script>
</head>
<body>
<div id='element'>
<div id='loader'>Loading....</div>
</div>
</body>
</html>
import { closest, enableRipple} from '@syncfusion/ej2-base';
import { BeforeOpenCloseMenuEventArgs, MenuComponent, MenuItemModel } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';
enableRipple(true);
class App extends React.Component<{}, {}> {
// Menu items definition
public menuItems: MenuItemModel[] = [
{
items: [
{ text: 'Open' },
{ text: 'Save' },
{ text: 'Exit' }
],
text: 'File'
},
{
items: [
{ text: 'Cut' },
{ text: 'Copy' },
{ text: 'Paste' }
],
text: 'Edit'
},
{
items: [
{ text: 'Toolbar' },
{ text: 'Sidebar' }
],
text: 'View'
},
{
items: [
{ text: 'Spelling & Grammar' },
{ text: 'Customize' },
{ text: 'Options' }
],
text: 'Tools'
},
{ text: 'Go' },
{ text: 'Help' }
];
public onBeforeOpen(args: BeforeOpenCloseMenuEventArgs) {
// Getting parent menu item element offset
const relativeOffset = closest(args.event.target as Element, '.e-menu-item').getBoundingClientRect();
// Getting sub menu wrapper element using closest method
const subMenuEle = closest(args.element, '.e-menu-wrapper') as HTMLElement;
subMenuEle.style.display = 'block';
args.top = (relativeOffset.top - subMenuEle.getBoundingClientRect().height) + pageYOffset;
args.left = relativeOffset.left + pageXOffset;
subMenuEle.style.display = '';
}
public render() {
return (
<MenuComponent items={this.menuItems} beforeOpen={this.onBeforeOpen}/>
);
}
}
ReactDom.render(<App />,document.getElementById('element'));
For custom positioning, set both
top
andleft
position in thebeforeOpen
event.