Overriding the Default Rendering

The Menu enables you to override the default rendering of its items.

To customize the item rendering, use any of the following approaches:

Items

By default, the innermost Menu item part includes only text.

To override the rendering of that innermost item part, either:

  • Override the innermost part for a specific item by using the render property.
import React from 'react';
import ReactDOM from 'react-dom';
import { Menu, MenuItem } from '@progress/kendo-react-layout';

const itemRender = (props) => `itemId: ${props.itemId}, text: ${props.item.text}`;

class App extends React.Component {
    render() {
        return (
            <Menu>
                <MenuItem text="Item1" render={itemRender} />
                <MenuItem text="Item2" icon="heart">
                    <MenuItem text="Item2.1" />
                    <MenuItem text="Item2.2" />
                </MenuItem>
            </Menu>
        );
    }
}
ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);
  • Override the innermost part for all items by using the itemRender property of the Menu.
import React from 'react';
import ReactDOM from 'react-dom';
import { Menu, MenuItem } from '@progress/kendo-react-layout';

const itemRender = (props) => `itemId: ${props.itemId}, text: ${props.item.text}`;

class App extends React.Component {
    render() {
        return (
            <Menu itemRender={itemRender}>
                <MenuItem text="Item1" />
                <MenuItem text="Item2" icon="heart">
                    <MenuItem text="Item2.1" />
                    <MenuItem text="Item2.2" />
                </MenuItem>
            </Menu>
        );
    }
}
ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

By default, the Menu item link includes an icon, text, and an arrow.

To override the rendering of the item link, either:

  • Override the item link for a specific item by using the linkRender property.
import React from 'react';
import ReactDOM from 'react-dom';
import { Menu, MenuItem, MenuItemLink, MenuItemArrow } from '@progress/kendo-react-layout';

const linkRender = (props) => {
    return (
        <MenuItemLink url={props.item.url} opened={props.opened}>
            {[
                renderMenuIconIfApplicable(props),
                props.item.text,
                renderArrowIfApplicable(props)
            ]}
        </MenuItemLink>
    );
};
function renderMenuIconIfApplicable(props) {
    return props.item.icon ? <span className={`k-icon k-i-${props.item.icon}`} role="presentation" key="0" /> : null;
}
function renderArrowIfApplicable(props) {
    return props.item.items && props.item.items.length > 0 ?
        <MenuItemArrow itemId={props.itemId} verticalMenu={false} dir={props.dir} key="1" /> : null;
}

class App extends React.Component {
    render() {
        return (
            <Menu>
                <MenuItem text="Item1" />
                <MenuItem text="Item2" icon="heart" linkRender={linkRender}>
                    <MenuItem text="Item2.1" />
                    <MenuItem text="Item2.2" />
                </MenuItem>
            </Menu>
        );
    }
}
ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);
  • Override the item link for all items by using the linkRender property of the Menu.
import React from 'react';
import ReactDOM from 'react-dom';
import { Menu, MenuItem, MenuItemLink, MenuItemArrow } from '@progress/kendo-react-layout';

const linkRender = (props) => {
    return (
        <MenuItemLink url={props.item.url} opened={props.opened}>
            {[
                renderMenuIconIfApplicable(props),
                props.item.text,
                renderArrowIfApplicable(props)
            ]}
        </MenuItemLink>
    );
};
function renderMenuIconIfApplicable(props) {
    return props.item.icon ? <span className={`k-icon k-i-${props.item.icon}`} role="presentation" key="0" /> : null;
}
function renderArrowIfApplicable(props) {
    return props.item.items && props.item.items.length > 0 ?
        <MenuItemArrow itemId={props.itemId} verticalMenu={false} dir={props.dir} key="1" /> : null;
}

class App extends React.Component {
    render() {
        return (
            <Menu linkRender={linkRender}>
                <MenuItem text="Item1" />
                <MenuItem text="Item2" icon="heart">
                    <MenuItem text="Item2.1" />
                    <MenuItem text="Item2.2" />
                </MenuItem>
            </Menu>
        );
    }
}
ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

Content

You can set specific content that will replace the children of a Menu item by using the contentRender property.

import React from 'react';
import ReactDOM from 'react-dom';
import { Menu, MenuItem } from '@progress/kendo-react-layout';

const contentRender = (props) => {
    return (
        <div style={{ padding: '10px' }}>Custom content for itemId: {props.itemId}, text: {props.item.text}</div>
    );
};

class App extends React.Component {
    render() {
        return (
            <Menu>
                <MenuItem text="Item1" contentRender={contentRender} />
                <MenuItem text="Item2" icon="heart">
                    <MenuItem text="Item2.1" />
                    <MenuItem text="Item2.2" />
                </MenuItem>
            </Menu>
        );
    }
}
ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);

If a component that is rendered inside the content utilizes a popup that is rendered outside the content, the Menu closes the item as soon as the user hovers over the popup. Even if the popup is rendered inside the content, it may still overflow, which will cause the mouse to leave the Menu when the popup is closed.

To avoid the accidental closing of content items:

  1. Set the ids of the content items to the customCloseItemIds property of the Menu.
  2. Provide a Close button.
import React from 'react';
import ReactDOM from 'react-dom';
import { Menu } from '@progress/kendo-react-layout';
import Content from './content.jsx';
import items from './items.json';

class App extends React.Component {
    menu;

    constructor(props) {
        super(props);
        this.state = { chosenFilter: '' };

        items.forEach(rootItem => {
            // Enhance the filter items with content and a bridging API that can be used by the content.
            Object.assign(rootItem.items[0], {
                contentRender: Content,
                data: {
                    resetMenu: this.resetMenu,
                    showChosenFilter: this.showChosenFilter,
                    clearFilter: this.clearFilter
                }
            });
        });
    }

    render() {
        return (
            <div>
                <Menu
                    items={items}
                    // Sets the ids of the items (i.e. the content items) that will be closed via a custom close button.
                    customCloseItemIds={['0_0_0', '1_0_0', '2_0_0']}
                    ref={el => this.menu = el}
                />
                <div>Filter info:</div>
                <div>{this.state.chosenFilter}</div>
            </div>
        );
    }

    resetMenu = () => {
        // Collapses the menu.
        this.menu.reset();
    }

    clearFilter = () => {
        this.setState({ chosenFilter: '' });
    }

    showChosenFilter = (itemId, filterValue) => {
        const rootItemIndex = itemId.split('_')[0];

        this.setState({ chosenFilter: `column: ${items[rootItemIndex].text} filtered with: ${filterValue}` });
    }
}

ReactDOM.render(
    <App />,
    document.querySelector('my-app')
);
 /