+<!-- uses dropdown menu CSS for easy stying, but it's not a dropdown -->
+<ng-template #contextMenu let-gridContext="gridContext">
+ <ng-container *ngFor="let action of gridContext.toolbarActions">
+ <ng-container *ngIf="action.separator">
+ <div class="dropdown-divider"></div>
+ </ng-container>
+ <ng-container *ngIf="!action.separator">
+ <a class="dropdown-item" (click)="performAction(action)">
+ <span class="ml-2">{{action.label}}</span>
+ </a>
+ </ng-container>
+ </ng-container>
+</ng-template>
+
<!--
tabindex=1 so the grid body can capture keyboard events.
-->
</ng-container>
</ng-container>
</div>
+ <!-- contextMenu applied to cells instead of rows so the position
+ of the popover is close to the mouse. As of writing, no way
+ to position the popover at the mouse -->
<div role="gridcell" class="eg-grid-cell eg-grid-body-cell"
[ngStyle]="{flex:col.flex}"
[ngClass]="{'eg-grid-cell-overflow': context.overflowCells}"
(dblclick)="onRowDblClick(row)"
(click)="onRowClick($event, row, idx)"
+ #rowContextMenu="ngbPopover"
+ popoverTitle="Actions for Selected Rows" i18n-popoverTitle
+ (contextmenu)="onRowContextClick($event, row, rowContextMenu)"
+ [ngbPopover]="contextMenu"
+ placement="bottom"
+ triggers="manual"
*ngFor="let col of context.columnSet.displayColumns()">
<eg-grid-body-cell [context]="context" [row]="row" [column]="col">
import {Component, Input, OnInit, Host} from '@angular/core';
import {GridContext, GridColumn, GridRowSelector,
- GridColumnSet, GridDataSource} from './grid';
+ GridToolbarAction, GridColumnSet, GridDataSource} from './grid';
import {GridComponent} from './grid.component';
+import {NgbPopover} from '@ng-bootstrap/ng-bootstrap';
@Component({
selector: 'eg-grid-body',
@Input() context: GridContext;
- constructor(@Host() private grid: GridComponent) {}
+ // Track the context menus so we can manually close them
+ // when another popover is opened.
+ contextMenus: NgbPopover[];
+
+ constructor(@Host() private grid: GridComponent) {
+ this.contextMenus = [];
+ }
ngOnInit() {}
}
}
- onRowClick($event: any, row: any, idx: number) {
+ handleRowClick($event: any, row: any) {
if (this.context.disableSelect) {
// Avoid any appearance or click behavior when row
} else {
this.context.selectOneRow(index);
}
+ }
+ onRowClick($event: any, row: any, idx: number) {
+ this.handleRowClick($event, row);
this.grid.onRowClick.emit(row);
}
this.grid.onRowActivate.emit(row);
}
+ performAction(action: GridToolbarAction) {
+ action.action(this.context.getSelectedRows());
+ }
+
+ // Apply row selection, track the new menu if needed,
+ // manually close any existing open menus, open selected menu.
+ onRowContextClick($event, row: any, contextMenu: NgbPopover) {
+ $event.preventDefault(); // prevent browser context menu
+
+ if (this.context.toolbarActions.length === 0) {
+ // No actions to render.
+ return;
+ }
+
+ this.handleRowClick($event, row);
+
+ const existing = this.contextMenus.filter(m => m === contextMenu)[0];
+ if (!existing) {
+ this.contextMenus.push(contextMenu);
+ }
+
+ // Force any previously opened menus to close, which does
+ // not naturally occur via context-click.
+ this.contextMenus.forEach(m => m.close());
+
+ contextMenu.open({gridContext: this.context});
+ }
}