Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

An Angular component to show a context menu on an arbitrary component

License

NotificationsYou must be signed in to change notification settings

isaacplmann/ngx-contextmenu

Repository files navigation

A context menu built with Angular (10) inspired byui.bootstrap.contextMenu. Bootstrap classes are included in the markup, but there is no explicit dependency on Bootstrap.DemoStackblitz example

Installation

  • npm install ngx-contextmenu @angular/cdk
  • import ContextMenuModule.forRoot() into your app module
  • Make sure to include<!doctype html> at the top of yourindex.html

Usage

Angular 5 support

Please use ngx-contextmenu@4.2.0 with Angular 5 projects.

Template

<ul><li*ngFor="let item of items"[contextMenu]="basicMenu"[contextMenuSubject]="item">Right Click: {{item?.name}}</li></ul><context-menu><ng-templatecontextMenuItem(execute)="showMessage('Hi, ' + $event.item.name)">    Say hi!</ng-template><ng-templatecontextMenuItemdivider="true"></ng-template><ng-templatecontextMenuItemlet-item(execute)="showMessage($event.item.name + ' said: ' + $event.item.otherProperty)">    Bye, {{item?.name}}</ng-template><ng-templatecontextMenuItempassive="true">    Input something:<inputtype="text"></ng-template></context-menu>

Component Code

@Component({  ...})exportclassMyContextMenuClass{publicitems=[{name:'John',otherProperty:'Foo'},{name:'Joe',otherProperty:'Bar'}];  @ViewChild(ContextMenuComponent)publicbasicMenu:ContextMenuComponent;}

Context Menu Items

  • Each context menu item is a<ng-template> element with thecontextMenuItem attribute directive applied.
  • If theitem object is used in the context menu item template, thelet-item attribute must be applied to the<ng-template> element.** Note: ** Make sure to use theitem?.property syntax in the template rather thanitem.property as the item will be initiallyundefined.
  • Every context menu item emitsexecute events. The$event object is of the form{ event: MouseEvent, item: any } whereevent is the mouse click eventthat triggered the execution anditem is the current item.
  • Thedivider input parameter is optional. Items default to normal menu items. Ifdivider istrue, all the other inputs are ignored.
  • Thepassive input parameter is optional. Ifpassive istrue, the menu item will not emit execute events or closethe context menu when clicked.
  • Theenabled input parameter is optional. Items are enabled by default.This can be a boolean value or a function definition that takes an item and returns a boolean.
  • Thevisible input parameter is optional. Items are visible by default. This property enables you to show certain context menu items based on what the data item is.This can be a boolean value or a function definition that takes an item and returns a boolean.
  • Within the template, you have access to any components and variables available in the outer context.
<context-menu><ng-templatecontextMenuItemlet-item[visible]="isMenuItemType1"[enabled]="false"(execute)="showMessage('Hi, ' + $event.item.name)">    Say hi, {{item?.name}}!<my-component[attribute]="item"></my-component>    With access to the outside context: {{ outsideValue }}</ng-template></context-menu>
publicoutsideValue="something";publicisMenuItemType1(item:any):boolean{returnitem.type==='type1';}

Sub-menus

You can specify sub-menus like this:

<ul><li*ngFor="let item of items"[contextMenu]="basicMenu"[contextMenuSubject]="item">Right Click: {{item?.name}}</li></ul><context-menu><ng-templatecontextMenuItem[subMenu]="saySubMenu">    Say...</ng-template><context-menu#saySubMenu><ng-templatecontextMenuItem(execute)="showMessage('Hi, ' + $event.item.name)">      ...hi!</ng-template><ng-templatecontextMenuItem(execute)="showMessage('Hola, ' + $event.item.name)">      ...hola!</ng-template><ng-templatecontextMenuItem(execute)="showMessage('Salut, ' + $event.item.name)">      ...salut!</ng-template></context-menu><ng-templatecontextMenuItemdivider="true"></ng-template><ng-templatecontextMenuItemlet-item(execute)="showMessage($event.item.name + ' said: ' + $event.item.otherProperty)">    Bye, {{item?.name}}</ng-template><ng-templatecontextMenuItempassive="true">    Input something:<inputtype="text"></ng-template></context-menu>

Notes:

  1. The sub<context-menu> can not be placed inside the<ng-template> that references it.
  2. Sub-menus may be nested as deeply as you wish.

Upgrade from angular2-contextmenu 0.x

  1. Changepackage.json to referencengx-contextmenu instead ofangular2-contextmenu
  2. Upgrade to@angular 4.x
  3. Use<ng-template> instead of<template>
  4. Update any styles that referenced.angular2-contextmenu to use.ngx-contextmenu instead

Note: The imperative way of declaring context menu items has been removed. i.e. You can't pass anactions property tocontextMenuService.show.next().

Usingvisible andenabled functions

If you need access to properties in your component from within theenabled orvisible functions, you can pass in an arrow function.

<ng-template...[visible]="isMenuItemOutsideValue">
publicoutsideValue="something";publicisMenuItemOutsideValue=(item:any):boolean=>{returnitem.type===this.outsideValue;}

Multiple Context Menus

You can use multiple context menus in the same component if you would like.

<ul><li*ngFor="let item of items"[contextMenu]="basicMenu"[contextMenuSubject]="item">{{item?.name}}</li></ul><context-menu#basicMenu>  ...</context-menu><ul><li*ngFor="let item of items"[contextMenu]="otherMenu"[contextMenuSubject]="item">{{item?.name}}</li></ul><context-menu#otherMenu>  ...</context-menu>
@ViewChild('basicMenu')public basicMenu:ContextMenuComponent;@ViewChild('otherMenu')public otherMenu:ContextMenuComponent;

Context Menu In a Different Component

If your<context-menu> component is in a different component from your list, you'll need to wire up the context menu event yourself.

<ul><li*ngFor="let item of items"(contextmenu)="onContextMenu($event, item)">Right Click: {{item.name}}</li></ul>
import{ContextMenuService}from'ngx-contextmenu';@Component({  ...})exportclassMyContextMenuClass{publicitems=[{name:'John',otherProperty:'Foo'},{name:'Joe',otherProperty:'Bar'}];// Optional  @Input()contextMenu:ContextMenuComponent;constructor(privatecontextMenuService:ContextMenuService){}publiconContextMenu($event:MouseEvent,item:any):void{this.contextMenuService.show.next({// Optional - if unspecified, all context menu components will opencontextMenu:this.contextMenu,event:$event,item:item,});$event.preventDefault();$event.stopPropagation();}}

Triggering the Context Menu with a Different Event

The context menu can be triggered at any point using the method above. For instance, to trigger the context menuwith a left click instead of a right click, use this html:

<ul><li*ngFor="let item of items"(click)="onContextMenu($event, item)">Left Click: {{item.name}}</li></ul>

This could be(keydown),(mouseover), or(myCustomEvent) as well.

Positioning the Context Menu around an element

If you want to override the context menu positioning to be appended to an element instead of based on mouse position,provide ananchorElement to thecontextMenuService. This makes sense if you want to trigger the context menu witha non-MouseEvent.

publiconContextMenu($event:KeyboardEvent,item: any):void{  this.contextMenuService.show.next({anchorElement:$event.target,// Optional - if unspecified, all context menu components will opencontextMenu:this.contextMenu,event:<any>$event,item:item,});$event.preventDefault();$event.stopPropagation();}

Custom Styles

The html that is generated for the context menu looks like this:

<divclass="dropdown ngx-contextmenu"><ulclass="dropdown-menu"><li><a><!-- the template for each context menu item goes here --></a><span><!-- the template for each passive context menu item goes here --></span></li></ul></div>

You can key off of thengx-contextmenu class to create your own styles. Note that theul.dropdown-menu will have inline styles applied forposition,display,left andtop so that it will be positioned at the cursor when you right-click.

.ngx-contextmenu .dropdown-menu {border: solid1px chartreuse;background-color: darkgreen;padding:0;}.ngx-contextmenuli {display: block;border-top: solid1px chartreuse;text-transform: uppercase;text-align: center;}.ngx-contextmenuli:first-child {border-top:none;}.ngx-contextmenua {color:chartreuse;display: block;padding:0.5em1em;}.ngx-contextmenua:hover {color:darkgreen;background-color:chartreuse;}

Bootstrap 4

If you're using Bootstrap 4, you can specify auseBootstrap4 property in theforRoot function of theContextMenuModule in order to get the appropriate class names. Like this:

@NgModule({import:[ContextMenuModule.forRoot({useBootstrap4:true,}),],})exportclassAppModule{}

Or, if you want to repeat yourself, you can add auseBootstrap4 attribute to eachcontext-menu component. Like this:

<context-menu[useBootstrap4]="true"></context-menu>

Different styling on menus

If you want to style one menu differently than other menus, you can add a custom style to the menu.

<context-menu[menuClass]="'mystyle'"></context-menu>

Please note that the style needs to be global to affect the menu, since the menu element is added to the page outside the component that triggers the menu.

AutoFocus

You can optionally set focus on the context menu whenever it opens. This enables a user to easily tab through the context menu items and press enter to select them.

@NgModule({import:[ContextMenuModule.forRoot({autoFocus:true,}),],})exportclassAppModule{}

Keyboard navigation

You can use the keyboard to manipulate the context menu. Note: Keyboard navigation should be used in conjunction withautoFocus, since key events are only captured when the context menu is focused.

KeyAction
ArrowDownMove to next menu item (wrapping)
ArrowUpMove to previous menu item (wrapping)
ArrowRightOpen submenu of current menu item if present
ArrowLeftClose current menu unless already at root menu
Enter | SpaceOpen submenu or execute current menu item
EscClose current menu

Disable Context Menu

If you need to disable the context menu, you can pass aboolean to the[disabled] input:

<context-menu[disabled]="true"></context-menu>

Close event emitter

There is a(close) output EventEmitter that you can subscribe to for notifications when the context menu closes (either by clicking outside or choosing a menu item).

<context-menu(close)="processContextMenuCloseEvent()"></context-menu>

Dynamic context menu

The items in the context menu are completely controlled by thecontextMenuActions object.

<ul><li*ngFor="item in items"[contextMenu]="myContextMenu"[contextMenuSubject]="item">Right Click: {{item.name}}</li></ul><context-menu#myContextMenu><ng-template*ngFor="let action of contextMenuActions"contextMenuItemlet-item[visible]="action.visible"[enabled]="action.enabled"[divider]="action.divider"(execute)="action.click($event.item)">    {{ action.html($event.item) }}</ng-template></context-menu>
@Component({  ...})exportclassMyContextMenuClass{publicitems=[{name:'John',otherProperty:'Foo',type:'type1'},{name:'Joe',otherProperty:'Bar',type:'type2'}];  @ViewChild(ContextMenuComponent)publiccontextMenu:ContextMenuComponent;publiccontextMenuActions=[{html:(item)=>`Say hi!`,click:(item)=>alert('Hi, '+item.name),enabled:(item)=>true,visible:(item)=>item.type==='type1',},{divider:true,visible:true,},{html:(item)=>`Something else`,click:(item)=>alert('Or not...'),enabled:(item)=>false,visible:(item)=>item.type==='type1',},];}

About

An Angular component to show a context menu on an arbitrary component

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors16


[8]ページ先頭

©2009-2025 Movatter.jp