Vaadin WC API reference

Description

<vaadin-context-menu> is a Web Component for creating context menus.

Items

Items is a higher level convenience API for defining a (hierarchical) menu structure for the component. If a menu item has a non-empty children set, a sub-menu with the child items is opened next to the parent menu on mouseover, tap or a right arrow keypress.

When an item is selected, <vaadin-context-menu> dispatches an "item-selected" event with the selected item as event.detail.value property. If item does not have keepOpen property the menu will be closed.

contextMenu.items = [
  { text: 'Menu Item 1', theme: 'primary', className: 'first', children:
    [
      { text: 'Menu Item 1-1', checked: true, keepOpen: true },
      { text: 'Menu Item 1-2' }
    ]
  },
  { component: 'hr' },
  { text: 'Menu Item 2', children:
    [
      { text: 'Menu Item 2-1' },
      { text: 'Menu Item 2-2', disabled: true }
    ]
  },
  { text: 'Menu Item 3', disabled: true, className: 'last' }
];

contextMenu.addEventListener('item-selected', e => {
  const item = e.detail.value;
  console.log(`${item.text} selected`);
});

NOTE: when the items array is defined, the renderer cannot be used.

Rendering

The content of the menu can be populated by using the renderer callback function.

The renderer function provides root, contextMenu, model arguments when applicable. Generate DOM content by using model object properties if needed, append it to the root element and control the state of the host element by accessing contextMenu. Before generating new content, the renderer function should check if there is already content in root for reusing it.

<vaadin-context-menu id="contextMenu">
 <p>This paragraph has a context menu.</p>
</vaadin-context-menu>
const contextMenu = document.querySelector('#contextMenu');
contextMenu.renderer = (root, contextMenu, context) => {
  let listBox = root.firstElementChild;
  if (!listBox) {
    listBox = document.createElement('vaadin-list-box');
    root.appendChild(listBox);
  }

  let item = listBox.querySelector('vaadin-item');
  if (!item) {
    item = document.createElement('vaadin-item');
    listBox.appendChild(item);
  }
  item.textContent = 'Content of the selector: ' + context.target.textContent;
};

You can access the menu context inside the renderer using context.target and context.detail.

Renderer is called on the opening of the context-menu and each time the related context is updated. DOM generated during the renderer call can be reused in the next renderer call and will be provided with the root argument. On first call it will be empty.

vaadin-contextmenu Gesture Event

vaadin-contextmenu is a gesture event (a custom event), which is dispatched after either contextmenu or long touch events. This enables support for both mouse and touch environments in a uniform way.

<vaadin-context-menu> opens the menu overlay on the vaadin-contextmenu event by default.

By default, the <vaadin-context-menu> element listens for the menu opening event on itself. In case if you do not want to wrap the target, you can listen for events on an element outside the <vaadin-context-menu> by setting the listenOn property:

<vaadin-context-menu id="contextMenu"></vaadin-context-menu>

<div id="menuListener">The element that listens for the contextmenu event.</div>
const contextMenu = document.querySelector('#contextMenu');
contextMenu.listenOn = document.querySelector('#menuListener');

Filtering Menu Targets

By default, the listener element and all its descendants open the context menu. You can filter the menu targets to a smaller set of elements inside the listener element by setting the selector property.

In the following example, only the elements matching .has-menu will open the context menu:

<vaadin-context-menu selector=".has-menu">
  <p class="has-menu">This paragraph opens the context menu</p>
  <p>This paragraph does not open the context menu</p>
</vaadin-context-menu>

The following properties are available in the context argument:

  • target is the menu opening event target, which is the element that the user has called the context menu for
  • detail is the menu opening event detail

In the following example, the menu item text is composed with the contents of the element that opened the menu:

<vaadin-context-menu selector="li" id="contextMenu">
  <ul>
    <li>Foo</li>
    <li>Bar</li>
    <li>Baz</li>
  </ul>
</vaadin-context-menu>
const contextMenu = document.querySelector('#contextMenu');
contextMenu.renderer = (root, contextMenu, context) => {
  let listBox = root.firstElementChild;
  if (!listBox) {
    listBox = document.createElement('vaadin-list-box');
    root.appendChild(listBox);
  }

  let item = listBox.querySelector('vaadin-item');
  if (!item) {
    item = document.createElement('vaadin-item');
    listBox.appendChild(item);
  }
  item.textContent = 'The menu target: ' + context.target.textContent;
};

Styling

The following shadow DOM parts are available for styling:

Part name Description
backdrop Backdrop of the overlay
overlay The overlay container
content The overlay content

See Styling Components documentation.

Internal components

When using items API the following internal components are themable:

The <vaadin-context-menu-item> sub-menu elements have the following additional state attributes on top of the built-in <vaadin-item> state attributes:

Attribute Description
expanded Expanded parent item.

Properties

closeOn

Type: string

Event name to listen for closing the context menu.

items

Type: ContextMenuItem[] | undefined

Defines a (hierarchical) menu structure for the component. If a menu item has a non-empty children set, a sub-menu with the child items is opened next to the parent menu on mouseover, tap or a right arrow keypress.

The items API can't be used together with a renderer!

Example

contextMenu.items = [
  { text: 'Menu Item 1', theme: 'primary', className: 'first', children:
    [
      { text: 'Menu Item 1-1', checked: true, keepOpen: true },
      { text: 'Menu Item 1-2' }
    ]
  },
  { component: 'hr' },
  { text: 'Menu Item 2', children:
    [
      { text: 'Menu Item 2-1' },
      { text: 'Menu Item 2-2', disabled: true }
    ]
  },
  { text: 'Menu Item 3', disabled: true, className: 'last' }
];

See also: ContextMenuItem

listenOn

Type: HTMLElement

The target element that's listened to for context menu opening events. By default the vaadin-context-menu listens to the target's vaadin-contextmenu events.

opened

Type: boolean

True if the overlay is currently displayed.

openOn

Type: string

Event name to listen for opening the context menu.

renderer

Type: ContextMenuRenderer | null | undefined

Custom function for rendering the content of the menu overlay. Receives three arguments:

  • root The root container DOM element. Append your content to it.
  • contextMenu The reference to the <vaadin-context-menu> element.
  • context The object with the menu context, contains:
    • context.target the target of the menu opening event,
    • context.detail the menu opening event detail.

See also: ContextMenuRenderer

selector

Type: string | null | undefined

CSS selector that can be used to target any child element of the context menu to listen for openOn events.

Methods

close

Type: () => void

Closes the overlay.

open

Type: (e: Event | undefined) => void

Opens the overlay.

requestContentUpdate

Type: () => void

Requests an update for the content of the menu overlay. While performing the update, it invokes the renderer passed in the renderer property.

It is not guaranteed that the update happens immediately (synchronously) after it is requested.

Events

closed

Type: ContextMenuClosedEvent

Fired when the context menu is closed.

item-selected

Type: ContextMenuItemSelectedEvent

Fired when an item is selected when the context menu is populated using the items API.

opened-changed

Type: ContextMenuOpenedChangedEvent

Fired when the opened property changes.

Types

ContextMenuClosedEvent

/**
 * Fired when the context menu is closed.
 */
export type ContextMenuClosedEvent = CustomEvent;

ContextMenuItem

export type ContextMenuItem<TItemData extends object = object> = {
  text?: string;
  component?: HTMLElement | string;
  disabled?: boolean;
  checked?: boolean;
  keepOpen?: boolean;
  theme?: string[] | string;
  className?: string;
  children?: Array<ContextMenuItem<TItemData>>;
} & TItemData;

ContextMenuItemSelectedEvent

/**
 * Fired when an item is selected when the context menu is populated using the `items` API.
 */
export type ContextMenuItemSelectedEvent<TItem extends ContextMenuItem = ContextMenuItem> = CustomEvent<{
  value: TItem;
}>;

ContextMenuOpenedChangedEvent

/**
 * Fired when the `opened` property changes.
 */
export type ContextMenuOpenedChangedEvent = CustomEvent<{ value: boolean }>;

ContextMenuRenderer

export type ContextMenuRenderer = (
  root: HTMLElement,
  contextMenu: ContextMenu,
  context: ContextMenuRendererContext,
) => void;

ContextMenuRendererContext

export interface ContextMenuRendererContext {
  target: HTMLElement;
  detail?: { sourceEvent: Event };
}