{"id":13497395,"url":"https://github.com/isaacplmann/ngx-contextmenu","last_synced_at":"2025-04-12T14:56:13.914Z","repository":{"id":19353407,"uuid":"86857399","full_name":"isaacplmann/ngx-contextmenu","owner":"isaacplmann","description":"An Angular component to show a context menu on an arbitrary component","archived":false,"fork":false,"pushed_at":"2024-01-16T06:32:35.000Z","size":14367,"stargazers_count":246,"open_issues_count":107,"forks_count":88,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-04-03T13:17:50.378Z","etag":null,"topics":["angular","angular-library","contextmenu","ngx"],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/isaacplmann.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-03-31T20:22:22.000Z","updated_at":"2025-02-08T21:04:45.000Z","dependencies_parsed_at":"2024-06-18T12:39:44.253Z","dependency_job_id":"f9e94899-d402-4563-85c1-8206a8621ad4","html_url":"https://github.com/isaacplmann/ngx-contextmenu","commit_stats":{"total_commits":93,"total_committers":21,"mean_commits":4.428571428571429,"dds":0.4086021505376344,"last_synced_commit":"92848194a2c2744a08355a0f42e25622d8d92ad0"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isaacplmann%2Fngx-contextmenu","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isaacplmann%2Fngx-contextmenu/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isaacplmann%2Fngx-contextmenu/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/isaacplmann%2Fngx-contextmenu/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/isaacplmann","download_url":"https://codeload.github.com/isaacplmann/ngx-contextmenu/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248586244,"owners_count":21128996,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","angular-library","contextmenu","ngx"],"created_at":"2024-07-31T20:00:30.356Z","updated_at":"2025-04-12T14:56:13.893Z","avatar_url":"https://github.com/isaacplmann.png","language":"TypeScript","funding_links":[],"categories":["Uncategorized","TypeScript","UI Components"],"sub_categories":["Uncategorized","Menu"],"readme":"# ngx-contextmenu\n\nA context menu built with Angular (10) inspired by [ui.bootstrap.contextMenu](https://github.com/Templarian/ui.bootstrap.contextMenu).  Bootstrap classes are included in the markup, but there is no explicit dependency on Bootstrap. [Demo](https://isaacplmann.github.io/ngx-contextmenu/) [Stackblitz example](https://stackblitz.com/edit/ngx-contextmenu-example)\n\n## Installation\n\n- `npm install ngx-contextmenu @angular/cdk`\n- import ContextMenuModule.forRoot() into your app module\n- Make sure to include `\u003c!doctype html\u003e` at the top of your `index.html`\n\n## Usage\n\n### Angular 5 support\n\nPlease use ngx-contextmenu@4.2.0 with Angular 5 projects.\n\n### Template\n\n```html\n\u003cul\u003e\n    \u003cli *ngFor=\"let item of items\" [contextMenu]=\"basicMenu\" [contextMenuSubject]=\"item\"\u003eRight Click: {{item?.name}}\u003c/li\u003e\n\u003c/ul\u003e\n\u003ccontext-menu\u003e\n  \u003cng-template contextMenuItem (execute)=\"showMessage('Hi, ' + $event.item.name)\"\u003e\n    Say hi!\n  \u003c/ng-template\u003e\n  \u003cng-template contextMenuItem divider=\"true\"\u003e\u003c/ng-template\u003e\n  \u003cng-template contextMenuItem let-item (execute)=\"showMessage($event.item.name + ' said: ' + $event.item.otherProperty)\"\u003e\n    Bye, {{item?.name}}\n  \u003c/ng-template\u003e\n  \u003cng-template contextMenuItem passive=\"true\"\u003e\n    Input something: \u003cinput type=\"text\"\u003e\n  \u003c/ng-template\u003e\n\u003c/context-menu\u003e\n```\n\n### Component Code\n\n```js\n@Component({\n  ...\n})\nexport class MyContextMenuClass {\n  public items = [\n      { name: 'John', otherProperty: 'Foo' },\n      { name: 'Joe', otherProperty: 'Bar' }\n  ];\n  @ViewChild(ContextMenuComponent) public basicMenu: ContextMenuComponent;\n}\n```\n\n## Context Menu Items\n\n- Each context menu item is a `\u003cng-template\u003e` element with the `contextMenuItem` attribute directive applied.\n- If the `item` object is used in the context menu item template, the `let-item` attribute must be applied to the `\u003cng-template\u003e` element. \n  ** Note: ** Make sure to use the `item?.property` syntax in the template rather than `item.property` as the item will be initially `undefined`.\n- Every context menu item emits `execute` events. The `$event` object is of the form `{ event: MouseEvent, item: any }` where `event` is the mouse click event\n  that triggered the execution and `item` is the current item.\n- The `divider` input parameter is optional.  Items default to normal menu items.  If `divider` is `true`, all the other inputs are ignored.\n- The `passive` input parameter is optional.  If `passive` is `true`, the menu item will not emit execute events or close\n  the context menu when clicked.\n- The `enabled` input parameter is optional.  Items are enabled by default.\n  This can be a boolean value or a function definition that takes an item and returns a boolean.\n- The `visible` 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.\n  This can be a boolean value or a function definition that takes an item and returns a boolean.\n- Within the template, you have access to any components and variables available in the outer context.\n\n```html\n\u003ccontext-menu\u003e\n  \u003cng-template contextMenuItem let-item [visible]=\"isMenuItemType1\" [enabled]=\"false\" (execute)=\"showMessage('Hi, ' + $event.item.name)\"\u003e\n    Say hi, {{item?.name}}!  \u003cmy-component [attribute]=\"item\"\u003e\u003c/my-component\u003e\n    With access to the outside context: {{ outsideValue }}\n  \u003c/ng-template\u003e\n\u003c/context-menu\u003e\n```\n```js\npublic outsideValue = \"something\";\npublic isMenuItemType1(item: any): boolean {\n  return item.type === 'type1';\n}\n```\n\n## Sub-menus\n\nYou can specify sub-menus like this:\n\n```html\n\u003cul\u003e\n    \u003cli *ngFor=\"let item of items\" [contextMenu]=\"basicMenu\" [contextMenuSubject]=\"item\"\u003eRight Click: {{item?.name}}\u003c/li\u003e\n\u003c/ul\u003e\n\u003ccontext-menu\u003e\n  \u003cng-template contextMenuItem [subMenu]=\"saySubMenu\"\u003e\n    Say...\n  \u003c/ng-template\u003e\n  \u003ccontext-menu #saySubMenu\u003e\n    \u003cng-template contextMenuItem (execute)=\"showMessage('Hi, ' + $event.item.name)\"\u003e\n      ...hi!\n    \u003c/ng-template\u003e\n    \u003cng-template contextMenuItem (execute)=\"showMessage('Hola, ' + $event.item.name)\"\u003e\n      ...hola!\n    \u003c/ng-template\u003e\n    \u003cng-template contextMenuItem (execute)=\"showMessage('Salut, ' + $event.item.name)\"\u003e\n      ...salut!\n    \u003c/ng-template\u003e\n  \u003c/context-menu\u003e\n  \u003cng-template contextMenuItem divider=\"true\"\u003e\u003c/ng-template\u003e\n  \u003cng-template contextMenuItem let-item (execute)=\"showMessage($event.item.name + ' said: ' + $event.item.otherProperty)\"\u003e\n    Bye, {{item?.name}}\n  \u003c/ng-template\u003e\n  \u003cng-template contextMenuItem passive=\"true\"\u003e\n    Input something: \u003cinput type=\"text\"\u003e\n  \u003c/ng-template\u003e\n\u003c/context-menu\u003e\n```\n\nNotes:\n1. The sub `\u003ccontext-menu\u003e` can not be placed inside the `\u003cng-template\u003e` that references it.\n2. Sub-menus may be nested as deeply as you wish.\n\n## Upgrade from angular2-contextmenu 0.x\n\n1. Change `package.json` to reference `ngx-contextmenu` instead of `angular2-contextmenu`\n2. Upgrade to `@angular` 4.x\n3. Use `\u003cng-template\u003e` instead of `\u003ctemplate\u003e`\n4. Update any styles that referenced `.angular2-contextmenu` to use `.ngx-contextmenu` instead\n\n**Note:** The imperative way of declaring context menu items has been removed.  i.e. You can't pass an `actions` property to `contextMenuService.show.next()`.\n\n## Using `visible` and `enabled` functions\n\nIf you need access to properties in your component from within the `enabled` or `visible` functions, you can pass in an arrow function.\n\n```html\n\u003cng-template ... [visible]=\"isMenuItemOutsideValue\"\u003e\n```\n```js\npublic outsideValue = \"something\";\npublic isMenuItemOutsideValue = (item: any): boolean =\u003e {\n  return item.type === this.outsideValue;\n}\n```\n\n## Multiple Context Menus\nYou can use multiple context menus in the same component if you would like.\n\n```html\n\u003cul\u003e\n    \u003cli *ngFor=\"let item of items\" [contextMenu]=\"basicMenu\" [contextMenuSubject]=\"item\"\u003e{{item?.name}}\u003c/li\u003e\n\u003c/ul\u003e\n\u003ccontext-menu #basicMenu\u003e\n  ...\n\u003c/context-menu\u003e\n\n\u003cul\u003e\n    \u003cli *ngFor=\"let item of items\" [contextMenu]=\"otherMenu\" [contextMenuSubject]=\"item\"\u003e{{item?.name}}\u003c/li\u003e\n\u003c/ul\u003e\n\u003ccontext-menu #otherMenu\u003e\n  ...\n\u003c/context-menu\u003e\n```\n\n```js\n@ViewChild('basicMenu') public basicMenu: ContextMenuComponent;\n@ViewChild('otherMenu') public otherMenu: ContextMenuComponent;\n```\n\n## Context Menu In a Different Component\nIf your `\u003ccontext-menu\u003e` component is in a different component from your list, you'll need to wire up the context menu event yourself.\n\n```html\n\u003cul\u003e\n    \u003cli *ngFor=\"let item of items\" (contextmenu)=\"onContextMenu($event, item)\"\u003eRight Click: {{item.name}}\u003c/li\u003e\n\u003c/ul\u003e\n```\n\n```js\nimport { ContextMenuService } from 'ngx-contextmenu';\n\n@Component({\n  ...\n})\nexport class MyContextMenuClass {\n  public items = [\n      { name: 'John', otherProperty: 'Foo' },\n      { name: 'Joe', otherProperty: 'Bar' }\n  ];\n\n  // Optional\n  @Input() contextMenu: ContextMenuComponent;\n\n  constructor(private contextMenuService: ContextMenuService) {}\n\n  public onContextMenu($event: MouseEvent, item: any): void {\n    this.contextMenuService.show.next({\n      // Optional - if unspecified, all context menu components will open\n      contextMenu: this.contextMenu,\n      event: $event,\n      item: item,\n    });\n    $event.preventDefault();\n    $event.stopPropagation();\n  }\n}\n```\n\n## Triggering the Context Menu with a Different Event\nThe context menu can be triggered at any point using the method above.  For instance, to trigger the context menu\nwith a left click instead of a right click, use this html:\n\n```html\n\u003cul\u003e\n    \u003cli *ngFor=\"let item of items\" (click)=\"onContextMenu($event, item)\"\u003eLeft Click: {{item.name}}\u003c/li\u003e\n\u003c/ul\u003e\n```\n\nThis could be `(keydown)`, `(mouseover)`, or `(myCustomEvent)` as well.\n\n## Positioning the Context Menu around an element\nIf you want to override the context menu positioning to be appended to an element instead of based on mouse position,\nprovide an `anchorElement` to the `contextMenuService`.  This makes sense if you want to trigger the context menu with\na non-MouseEvent.\n\n```ts\npublic onContextMenu($event: KeyboardEvent, item: any): void {\n  this.contextMenuService.show.next({\n    anchorElement: $event.target,\n    // Optional - if unspecified, all context menu components will open\n    contextMenu: this.contextMenu,\n    event: \u003cany\u003e$event,\n    item: item,\n  });\n  $event.preventDefault();\n  $event.stopPropagation();\n}\n```\n\n## Custom Styles\n\nThe html that is generated for the context menu looks like this:\n\n```html\n\u003cdiv class=\"dropdown ngx-contextmenu\"\u003e\n  \u003cul class=\"dropdown-menu\"\u003e\n    \u003cli\u003e\n      \u003ca\u003e\u003c!-- the template for each context menu item goes here --\u003e\u003c/a\u003e\n      \u003cspan\u003e\u003c!-- the template for each passive context menu item goes here --\u003e\u003c/span\u003e\n    \u003c/li\u003e\n  \u003c/ul\u003e\n\u003c/div\u003e\n```\n\nYou can key off of the `ngx-contextmenu` class to create your own styles.  Note that the `ul.dropdown-menu` will have inline styles applied for `position`, `display`, `left` and `top` so that it will be positioned at the cursor when you right-click.\n\n```css\n.ngx-contextmenu .dropdown-menu {\n  border: solid 1px chartreuse;\n  background-color: darkgreen;\n  padding: 0;\n}\n.ngx-contextmenu li {\n  display: block;\n  border-top: solid 1px chartreuse;\n  text-transform: uppercase;\n  text-align: center;\n}\n.ngx-contextmenu li:first-child {\n  border-top:none;\n}\n.ngx-contextmenu a {\n  color:chartreuse;\n  display: block;\n  padding: 0.5em 1em;\n}\n.ngx-contextmenu a:hover {\n  color:darkgreen;\n  background-color:chartreuse;\n}\n```\n\n## Bootstrap 4\n\nIf you're using Bootstrap 4, you can specify a `useBootstrap4` property in the `forRoot` function of the `ContextMenuModule` in order to get the appropriate class names.  Like this:\n\n```js\n@NgModule({\n  import: [\n    ContextMenuModule.forRoot({\n      useBootstrap4: true,\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n**Or, if you want to repeat yourself,** you can add a `useBootstrap4` attribute to each `context-menu` component.  Like this:\n\n```html\n\u003ccontext-menu [useBootstrap4]=\"true\"\u003e\u003c/context-menu\u003e\n```\n\n## Different styling on menus\n\nIf you want to style one menu differently than other menus, you can add a custom style to the menu.\n\n```html\n\u003ccontext-menu [menuClass]=\"'mystyle'\"\u003e\u003c/context-menu\u003e\n```\n\nPlease 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.\n\n## AutoFocus\n\nYou 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.\n\n```js\n@NgModule({\n  import: [\n    ContextMenuModule.forRoot({\n      autoFocus: true,\n    }),\n  ],\n})\nexport class AppModule {}\n```\n\n## Keyboard navigation\n\nYou can use the keyboard to manipulate the context menu.  Note: Keyboard navigation should be used in conjunction with `autoFocus`, since key events are only captured when the context menu is focused.\n\n| Key            | Action                                         |\n|:--------------:|------------------------------------------------|\n| ArrowDown      | Move to next menu item (wrapping)              |\n| ArrowUp        | Move to previous menu item (wrapping)          |\n| ArrowRight     | Open submenu of current menu item if present   |\n| ArrowLeft      | Close current menu unless already at root menu |\n| Enter \\| Space | Open submenu or execute current menu item      |\n| Esc            | Close current menu                             |\n\n## Disable Context Menu\n\nIf you need to disable the context menu, you can pass a `boolean` to the `[disabled]` input:\n\n```html\n\u003ccontext-menu [disabled]=\"true\"\u003e\u003c/context-menu\u003e\n```\n\n## Close event emitter\n\nThere 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).\n\n```html\n\u003ccontext-menu (close)=\"processContextMenuCloseEvent()\"\u003e\u003c/context-menu\u003e\n```\n\n## Dynamic context menu\n\nThe items in the context menu are completely controlled by the `contextMenuActions` object.\n\n```html\n\u003cul\u003e\n    \u003cli *ngFor=\"item in items\" [contextMenu]=\"myContextMenu\" [contextMenuSubject]=\"item\"\u003eRight Click: {{item.name}}\u003c/li\u003e\n\u003c/ul\u003e\n\u003ccontext-menu #myContextMenu\u003e\n  \u003cng-template *ngFor=\"let action of contextMenuActions\" contextMenuItem let-item\n    [visible]=\"action.visible\" [enabled]=\"action.enabled\" [divider]=\"action.divider\"\n    (execute)=\"action.click($event.item)\"\u003e\n    {{ action.html($event.item) }}\n  \u003c/ng-template\u003e\n\u003c/context-menu\u003e\n```\n\n```ts\n@Component({\n  ...\n})\nexport class MyContextMenuClass {\n  public items = [\n      { name: 'John', otherProperty: 'Foo', type: 'type1' },\n      { name: 'Joe', otherProperty: 'Bar', type: 'type2' }\n  ];\n  @ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent;\n  public contextMenuActions = [\n        {\n          html: (item) =\u003e `Say hi!`,\n          click: (item) =\u003e alert('Hi, ' + item.name),\n          enabled: (item) =\u003e true,\n          visible: (item) =\u003e item.type === 'type1',\n        },\n        {\n          divider: true,\n          visible: true,\n        },\n        {\n          html: (item) =\u003e `Something else`,\n          click: (item) =\u003e alert('Or not...'),\n          enabled: (item) =\u003e false,\n          visible: (item) =\u003e item.type === 'type1',\n        },\n      ];\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisaacplmann%2Fngx-contextmenu","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fisaacplmann%2Fngx-contextmenu","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fisaacplmann%2Fngx-contextmenu/lists"}