Search results

Template

Table in Sub ContextMenu

Menu items of the ContextMenu can be customized according to the requirement. The section explains about how to customize table template in sub menu item.

This can be achieved by appending table layout while li rendering by using beforeItemRender event.

Source
Preview
index.tsx
index.html
index.css
index.jsx
import { 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);

class App extends React.Component<{}, {}> {
    private menuItems: MenuItemModel[] = [
        {
            iconCss: 'e-cm-icons e-cut',
            text: 'Cut',
        },
        {
            iconCss: 'e-icons e-copy',
            text: 'Copy'
        },
        {
            iconCss: 'e-cm-icons e-paste',
            text: 'Paste'
        },
        {
            separator: true
        },
        {
            iconCss: 'e-icons e-link',
            text: 'Link'
        },
        {
            iconCss: 'e-icons e-table',
            items: [
                {
                    id: 'table'
                }
            ],
            text: 'Table'
        }
    ];
    public createHeader = () => {
        const header = document.createElement('h4');
        header.textContent = 'Insert Table';
        return header;
    }
    public createTable = () => {
        const table = document.createElement('table');
        for (let i: number = 0; i < 5; i++) {
            const row = document.createElement('tr');
            table.appendChild(row);
            for (let j: number = 0; j < 6; j++) {
                const col = document.createElement('td');
                row.appendChild(col);
                col.setAttribute('class', 'data');
            }
        }
        return table;
    }

    public itemBeforeEvent: any = (args: MenuEventArgs) => {
        if (args.item.id === 'table') {
            args.element.classList.add('bg-transparent');
            args.element.appendChild(this.createHeader());
            args.element.appendChild(this.createTable());
        }
    }

    public render() {
        return (
            <div className="container">
                <div id='target'>Right click / Touch hold to open the ContextMenu</div>
                <ContextMenuComponent id='contextmenu' target='#target'
                    items={this.menuItems} beforeItemRender={this.itemBeforeEvent}/>
            </div>
        );
    }
}

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/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/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>
<style>
  .e-contextmenu-wrapper ul .e-menu-item.bg-transparent {
    background-color: transparent;
    line-height: normal;
    height: auto;
  }
  h4 {
    text-align: center;
    margin-top: 5px;
    margin-bottom: 5px;
  }
</style>
<body>
    <div id='element'>
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>
#loader {
	color: #008cff;
	height: 40px;
	left: 45%;
	position: absolute;
	top: 45%;
	width: 30%;
}

#target {
	border: 1px dashed;
	height: 150px;
	padding: 10px;
	position: relative;
	text-align: justify;
	color: gray;
	user-select: none;
}

.data {
	border: 1px solid #212121;
	padding: 8px;
}

@font-face {
font-family: 'ddb-icons';
src:
url(data:application/x-font-ttf;charset=utf-8;base64,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) format('truetype');
font-weight: normal;
font-style: normal;
}

.e-cm-icons {
 font-family: 'ddb-icons' !important;
speak: none;
font-size: 55px;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}

.e-cut::before {
  content: '\e700';
}

.e-copy::before {
  content: '\e70a';
}

.e-paste::before {
  content: '\e701';
}

.e-link::before {
  content: '\e290';
}

.e-table::before {
  content: '\e705';
}
import { 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);
class App extends React.Component {
    constructor() {
        super(...arguments);
        this.menuItems = [
            {
                iconCss: 'e-cm-icons e-cut',
                text: 'Cut',
            },
            {
                iconCss: 'e-icons e-copy',
                text: 'Copy'
            },
            {
                iconCss: 'e-cm-icons e-paste',
                text: 'Paste'
            },
            {
                separator: true
            },
            {
                iconCss: 'e-icons e-link',
                text: 'Link'
            },
            {
                iconCss: 'e-icons e-table',
                items: [
                    {
                        id: 'table'
                    }
                ],
                text: 'Table'
            }
        ];
        this.createHeader = () => {
            const header = document.createElement('h4');
            header.textContent = 'Insert Table';
            return header;
        };
        this.createTable = () => {
            const table = document.createElement('table');
            for (let i = 0; i < 5; i++) {
                const row = document.createElement('tr');
                table.appendChild(row);
                for (let j = 0; j < 6; j++) {
                    const col = document.createElement('td');
                    row.appendChild(col);
                    col.setAttribute('class', 'data');
                }
            }
            return table;
        };
        this.itemBeforeEvent = (args) => {
            if (args.item.id === 'table') {
                args.element.classList.add('bg-transparent');
                args.element.appendChild(this.createHeader());
                args.element.appendChild(this.createTable());
            }
        };
    }
    render() {
        return (<div className="container">
                <div id='target'>Right click / Touch hold to open the ContextMenu</div>
                <ContextMenuComponent id='contextmenu' target='#target' items={this.menuItems} beforeItemRender={this.itemBeforeEvent}/>
            </div>);
    }
}
ReactDom.render(<App />, document.getElementById('element'));

UI Components in ContextMenu

UI components can also be placed inside the each li element of ContextMenu.

In the following example, CheckBox component is placed inside each li element and this can be achieved by creating CheckBox component in beforeItemRender event and appending it into the li element.

Source
Preview
index.tsx
index.html
index.css
index.jsx
import { closest, createElement, enableRipple} from '@syncfusion/ej2-base';
import { createCheckBox } from '@syncfusion/ej2-buttons';
import { BeforeOpenCloseMenuEventArgs, ContextMenuComponent, MenuEventArgs, MenuItemModel } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';

enableRipple(true);

class App extends React.Component<{}, {}> {

    public menuItems: MenuItemModel[] = [
        { text: 'Option 1' },
        { text: 'Option 2' },
        { text: 'Option 3' }
    ];
    public itemBeforeEvent: any = (args: MenuEventArgs) => {
        const check = createCheckBox(createElement, false, {
            checked: (args.item.text === 'Option 1' || args.item.text === 'Option 2') ? true : false,
            label: args.item.text
        });
        args.element.innerHTML = '';
        args.element.appendChild(check);
    }

    public beforeClose: any = (args: BeforeOpenCloseMenuEventArgs) => {
        if (closest((args.event.target as HTMLElement), '.e-menu-item')) {
            args.cancel = true;
            const selectedElem = args.element.querySelectorAll('.e-selected');
            for (const elem of selectedElem as any) {
                const ele = elem as HTMLElement;
                ele.classList.remove('e-selected');
            }
            const checkbox = closest(args.event.target as Element, '.e-checkbox-wrapper') as HTMLElement;
            const frame = checkbox.querySelector('.e-frame');
            if (checkbox && frame.classList.contains('e-check')) {
                frame.classList.remove('e-check');
            } else if (checkbox) {
                frame.classList.add('e-check');
            }
        }
    }
    public render() {
        return (
            <div className="container">
                <div id='target'>Right click / Touch hold to open the ContextMenu</div>
                <ContextMenuComponent id='contextmenu' target='#target' items={this.menuItems} beforeItemRender={this.itemBeforeEvent} beforeClose={this.beforeClose} />
            </div>
        );
    }
}
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/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-lists/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/ej2-popups/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/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>
#loader {
	color: #008cff;
	height: 40px;
	left: 45%;
	position: absolute;
	top: 45%;
	width: 30%;
}

.e-link::before {
content: '\e7e8';
}

#target {
	border: 1px dashed;
	height: 150px;
	padding: 10px;
	position: relative;
	text-align: justify;
	color: gray;
	user-select: none;
}
import { closest, createElement, enableRipple } from '@syncfusion/ej2-base';
import { createCheckBox } from '@syncfusion/ej2-buttons';
import { ContextMenuComponent } 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);
        this.menuItems = [
            { text: 'Option 1' },
            { text: 'Option 2' },
            { text: 'Option 3' }
        ];
        this.itemBeforeEvent = (args) => {
            const check = createCheckBox(createElement, false, {
                checked: (args.item.text === 'Option 1' || args.item.text === 'Option 2') ? true : false,
                label: args.item.text
            });
            args.element.innerHTML = '';
            args.element.appendChild(check);
        };
        this.beforeClose = (args) => {
            if (closest(args.event.target, '.e-menu-item')) {
                args.cancel = true;
                const selectedElem = args.element.querySelectorAll('.e-selected');
                for (const elem of selectedElem) {
                    const ele = elem;
                    ele.classList.remove('e-selected');
                }
                const checkbox = closest(args.event.target, '.e-checkbox-wrapper');
                const frame = checkbox.querySelector('.e-frame');
                if (checkbox && frame.classList.contains('e-check')) {
                    frame.classList.remove('e-check');
                }
                else if (checkbox) {
                    frame.classList.add('e-check');
                }
            }
        };
    }
    render() {
        return (<div className="container">
                <div id='target'>Right click / Touch hold to open the ContextMenu</div>
                <ContextMenuComponent id='contextmenu' target='#target' items={this.menuItems} beforeItemRender={this.itemBeforeEvent} beforeClose={this.beforeClose}/>
            </div>);
    }
}
ReactDom.render(<App />, document.getElementById('element'));