Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/isaacplmann/ngx-contextmenu
An Angular component to show a context menu on an arbitrary component
https://github.com/isaacplmann/ngx-contextmenu
angular angular-library contextmenu ngx
Last synced: 4 days ago
JSON representation
An Angular component to show a context menu on an arbitrary component
- Host: GitHub
- URL: https://github.com/isaacplmann/ngx-contextmenu
- Owner: isaacplmann
- License: mit
- Created: 2017-03-31T20:22:22.000Z (over 7 years ago)
- Default Branch: master
- Last Pushed: 2024-01-16T06:32:35.000Z (11 months ago)
- Last Synced: 2024-11-30T03:12:41.879Z (12 days ago)
- Topics: angular, angular-library, contextmenu, ngx
- Language: TypeScript
- Size: 13.7 MB
- Stars: 248
- Watchers: 12
- Forks: 91
- Open Issues: 107
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
- awesome-angular - ngx-contextmenu - An Angular component to show a context menu on an arbitrary component. (Uncategorized / Uncategorized)
- awesome-angular-components - isaacplmann/ngx-contextmenu - An Angular component to show a context menu on an arbitrary component (UI Components / Menu)
README
# ngx-contextmenu
A 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)
## Installation
- `npm install ngx-contextmenu @angular/cdk`
- import ContextMenuModule.forRoot() into your app module
- Make sure to include `` at the top of your `index.html`## Usage
### Angular 5 support
Please use [email protected] with Angular 5 projects.
### Template
```html
- Right Click: {{item?.name}}
Say hi!
Bye, {{item?.name}}
Input something:
```
### Component Code
```js
@Component({
...
})
export class MyContextMenuClass {
public items = [
{ name: 'John', otherProperty: 'Foo' },
{ name: 'Joe', otherProperty: 'Bar' }
];
@ViewChild(ContextMenuComponent) public basicMenu: ContextMenuComponent;
}
```
## Context Menu Items
- Each context menu item is a `` element with the `contextMenuItem` attribute directive applied.
- If the `item` object is used in the context menu item template, the `let-item` attribute must be applied to the `` element.
** Note: ** Make sure to use the `item?.property` syntax in the template rather than `item.property` as the item will be initially `undefined`.
- 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
that triggered the execution and `item` is the current item.
- The `divider` input parameter is optional. Items default to normal menu items. If `divider` is `true`, all the other inputs are ignored.
- The `passive` input parameter is optional. If `passive` is `true`, the menu item will not emit execute events or close
the context menu when clicked.
- The `enabled` 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.
- 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.
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.
```html
Say hi, {{item?.name}}!
With access to the outside context: {{ outsideValue }}
```
```js
public outsideValue = "something";
public isMenuItemType1(item: any): boolean {
return item.type === 'type1';
}
```
## Sub-menus
You can specify sub-menus like this:
```html
- Right Click: {{item?.name}}
Say...
...hi!
...hola!
...salut!
Bye, {{item?.name}}
Input something:
```
Notes:
1. The sub `` can not be placed inside the `` that references it.
2. Sub-menus may be nested as deeply as you wish.
## Upgrade from angular2-contextmenu 0.x
1. Change `package.json` to reference `ngx-contextmenu` instead of `angular2-contextmenu`
2. Upgrade to `@angular` 4.x
3. Use `` instead of ``
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 an `actions` property to `contextMenuService.show.next()`.
## Using `visible` and `enabled` functions
If you need access to properties in your component from within the `enabled` or `visible` functions, you can pass in an arrow function.
```html
```
```js
public outsideValue = "something";
public isMenuItemOutsideValue = (item: any): boolean => {
return item.type === this.outsideValue;
}
```
## Multiple Context Menus
You can use multiple context menus in the same component if you would like.
```html
- {{item?.name}}
...
- {{item?.name}}
...
```
```js
@ViewChild('basicMenu') public basicMenu: ContextMenuComponent;
@ViewChild('otherMenu') public otherMenu: ContextMenuComponent;
```
## Context Menu In a Different Component
If your `` component is in a different component from your list, you'll need to wire up the context menu event yourself.
```html
- Right Click: {{item.name}}
```
```js
import { ContextMenuService } from 'ngx-contextmenu';
@Component({
...
})
export class MyContextMenuClass {
public items = [
{ name: 'John', otherProperty: 'Foo' },
{ name: 'Joe', otherProperty: 'Bar' }
];
// Optional
@Input() contextMenu: ContextMenuComponent;
constructor(private contextMenuService: ContextMenuService) {}
public onContextMenu($event: MouseEvent, item: any): void {
this.contextMenuService.show.next({
// Optional - if unspecified, all context menu components will open
contextMenu: 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 menu
with a left click instead of a right click, use this html:
```html
- Left Click: {{item.name}}
```
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 an `anchorElement` to the `contextMenuService`. This makes sense if you want to trigger the context menu with
a non-MouseEvent.
```ts
public onContextMenu($event: KeyboardEvent, item: any): void {
this.contextMenuService.show.next({
anchorElement: $event.target,
// Optional - if unspecified, all context menu components will open
contextMenu: this.contextMenu,
event: $event,
item: item,
});
$event.preventDefault();
$event.stopPropagation();
}
```
## Custom Styles
The html that is generated for the context menu looks like this:
```html
```
You 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.
```css
.ngx-contextmenu .dropdown-menu {
border: solid 1px chartreuse;
background-color: darkgreen;
padding: 0;
}
.ngx-contextmenu li {
display: block;
border-top: solid 1px chartreuse;
text-transform: uppercase;
text-align: center;
}
.ngx-contextmenu li:first-child {
border-top:none;
}
.ngx-contextmenu a {
color:chartreuse;
display: block;
padding: 0.5em 1em;
}
.ngx-contextmenu a:hover {
color:darkgreen;
background-color:chartreuse;
}
```
## Bootstrap 4
If 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:
```js
@NgModule({
import: [
ContextMenuModule.forRoot({
useBootstrap4: true,
}),
],
})
export class AppModule {}
```
**Or, if you want to repeat yourself,** you can add a `useBootstrap4` attribute to each `context-menu` component. Like this:
```html
```
## Different styling on menus
If you want to style one menu differently than other menus, you can add a custom style to the menu.
```html
```
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.
```js
@NgModule({
import: [
ContextMenuModule.forRoot({
autoFocus: true,
}),
],
})
export class AppModule {}
```
## Keyboard navigation
You 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.
| Key | Action |
|:--------------:|------------------------------------------------|
| ArrowDown | Move to next menu item (wrapping) |
| ArrowUp | Move to previous menu item (wrapping) |
| ArrowRight | Open submenu of current menu item if present |
| ArrowLeft | Close current menu unless already at root menu |
| Enter \| Space | Open submenu or execute current menu item |
| Esc | Close current menu |
## Disable Context Menu
If you need to disable the context menu, you can pass a `boolean` to the `[disabled]` input:
```html
```
## 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).
```html
```
## Dynamic context menu
The items in the context menu are completely controlled by the `contextMenuActions` object.
```html
- Right Click: {{item.name}}
{{ action.html($event.item) }}
```
```ts
@Component({
...
})
export class MyContextMenuClass {
public items = [
{ name: 'John', otherProperty: 'Foo', type: 'type1' },
{ name: 'Joe', otherProperty: 'Bar', type: 'type2' }
];
@ViewChild(ContextMenuComponent) public contextMenu: ContextMenuComponent;
public contextMenuActions = [
{
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',
},
];
}
```