Search results

Data Binding in React ContextMenu component

In the following example, menu items are populated from data source and mapped to items property.

Source
Preview
index.tsx
index.html
index.css
datasource.tsx
index.jsx
import { ContextMenuComponent, MenuEventArgs, MenuItemModel } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';
// @ts-ignore
import { data, IRecord } from '../datasource.tsx';


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

    public getMenuItems = () => {
        let record: IRecord;
        const menuItems: MenuItemModel[] = [];
        for (const d of data) {
            record = d as IRecord;
            if (record.parentId) {
                if (!menuItems[record.parentId - 1].items) {
                    menuItems[record.parentId - 1].items = [];
                }
                menuItems[record.parentId - 1].items.push({ text: record.text });
            } else {
                menuItems.push({ text: record.text });
            }
        }
        return menuItems;
    }

    public itemBeforeEvent: any = (args: MenuEventArgs) => {
        if (!args.item.text) {
            args.element.classList.add('e-separator');
        }
    }

    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.getMenuItems()} 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>

<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;
}
export let data: IRecord[] = [
    { id: 1, parentId: null, text: 'View' },
    { id: 2, parentId: null, text: 'Sort by' },
    { id: 3, parentId: null, text: '' },
    { id: 4, parentId: null, text: 'New' },
    { id: 5, parentId: null, text: '' },
    { id: 6, parentId: null, text: 'Display Settings' },
    { id: 7, parentId: null, text: 'Personalize' },
    //first level child
    { id: 8, parentId: 1, text: 'Large Icons' },
    { id: 9, parentId: 1, text: 'Medium Icons' },
    { id: 10, parentId: 1, text: 'Small Icons' },
    { id: 11, parentId: 2, text: 'Name' },
    { id: 12, parentId: 2, text: 'Size' },
    { id: 13, parentId: 4, text: 'Folder' },
    { id: 14, parentId: 4, text: 'Shortcut' },
    { id: 15, parentId: 4, text: '' },
    { id: 16, parentId: 4, text: 'Contact' }
];

export interface IRecord {
    id: number,
    parentId: number,
    text: string
}
import { ContextMenuComponent } from '@syncfusion/ej2-react-navigations';
import * as React from 'react';
import * as ReactDom from 'react-dom';
// @ts-ignore
import { data } from '../datasource.tsx';
class App extends React.Component {
    constructor() {
        super(...arguments);
        this.getMenuItems = () => {
            let record;
            const menuItems = [];
            for (const d of data) {
                record = d;
                if (record.parentId) {
                    if (!menuItems[record.parentId - 1].items) {
                        menuItems[record.parentId - 1].items = [];
                    }
                    menuItems[record.parentId - 1].items.push({ text: record.text });
                }
                else {
                    menuItems.push({ text: record.text });
                }
            }
            return menuItems;
        };
        this.itemBeforeEvent = (args) => {
            if (!args.item.text) {
                args.element.classList.add('e-separator');
            }
        };
    }
    render() {
        return (<div className="container">
                <div id='target'>Right click / Touch hold to open the ContextMenu</div>
                <ContextMenuComponent id='contextmenu' target='#target' items={this.getMenuItems()} beforeItemRender={this.itemBeforeEvent}/>
            </div>);
    }
}
ReactDom.render(<App />, document.getElementById('element'));

While accessing Array we got the exception ‘object is possibly undefined’ due to ‘strictNullChecks’ option. So you can disable it in ‘tsconfig.json’ file.