src/app/core/entity-details/entity-actions-menu/entity-actions-menu.component.ts
OnChanges
selector | app-entity-actions-menu |
imports |
MatButtonModule
FontAwesomeModule
MatMenuModule
Angulartics2Module
DisableEntityOperationDirective
MatTooltipModule
|
styleUrls | ./entity-actions-menu.component.scss |
templateUrl | ./entity-actions-menu.component.html |
Properties |
Methods |
|
Inputs |
Outputs |
constructor(entityActionsMenuService: EntityActionsMenuService, viewContext: ViewComponentContext)
|
|||||||||
Parameters :
|
entity | |
Type : Entity
|
|
navigateOnDelete | |
Type : boolean
|
|
Default value : false
|
|
whether the "delete" action will trigger a navigation back to the parent list. This is useful when the entity is deleted from a fullscreen detail view but not for an overlay. |
showExpanded | |
Type : boolean
|
|
Whether some buttons should be displayed directly, outside the three-dot menu in dialog views. |
actionTriggered | |
Type : EventEmitter
|
|
Async executeAction | ||||||
executeAction(action: EntityAction)
|
||||||
Parameters :
Returns :
any
|
actions |
Type : EntityAction[]
|
The actions being displayed as menu items. |
import {
Component,
EventEmitter,
Input,
OnChanges,
Optional,
Output,
SimpleChanges,
} from "@angular/core";
import { Entity } from "../../entity/model/entity";
import { MatButtonModule } from "@angular/material/button";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { MatMenuModule } from "@angular/material/menu";
import { Angulartics2Module } from "angulartics2";
import { DisableEntityOperationDirective } from "../../permissions/permission-directive/disable-entity-operation.directive";
import { MatTooltipModule } from "@angular/material/tooltip";
import { ViewComponentContext } from "../../ui/abstract-view/view-component-context";
import { EntityActionsMenuService } from "./entity-actions-menu.service";
import { EntityAction } from "./entity-action.interface";
@Component({
selector: "app-entity-actions-menu",
templateUrl: "./entity-actions-menu.component.html",
styleUrls: ["./entity-actions-menu.component.scss"],
imports: [
MatButtonModule,
FontAwesomeModule,
MatMenuModule,
Angulartics2Module,
DisableEntityOperationDirective,
MatTooltipModule,
],
})
export class EntityActionsMenuComponent implements OnChanges {
@Input() entity: Entity;
/**
* whether the "delete" action will trigger a navigation back to the parent list.
* This is useful when the entity is deleted from a fullscreen detail view but not for an overlay.
*/
@Input() navigateOnDelete: boolean = false;
@Output() actionTriggered = new EventEmitter<string>();
/**
* The actions being displayed as menu items.
*/
actions: EntityAction[];
/**
* Whether some buttons should be displayed directly, outside the three-dot menu in dialog views.
*/
@Input() showExpanded?: boolean;
constructor(
private entityActionsMenuService: EntityActionsMenuService,
@Optional() protected viewContext: ViewComponentContext,
) {}
ngOnChanges(changes: SimpleChanges): void {
if (changes.entity) {
this.filterAvailableActions();
}
}
private async filterAvailableActions() {
if (!this.entity) {
this.actions = [];
return;
}
const allActions: EntityAction[] = this.entityActionsMenuService.getActions(
this.entity,
);
// check each action’s `visible` property to hide actions not applicable to the current entity
const visibleActions = (
await Promise.all(
allActions.map(async (action) => {
const isVisible = action.visible
? await action.visible(this.entity)
: true;
return isVisible ? action : null;
}),
)
).filter(Boolean) as EntityAction[];
this.actions = visibleActions;
}
async executeAction(action: EntityAction) {
const result = await action.execute(
this.entity,
this.navigateOnDelete && !this.viewContext?.isDialog,
);
if (result) {
this.actionTriggered.emit(action.action);
}
setTimeout(() => this.filterAvailableActions());
}
}
@if (!entity?.isNew) {
<!-- inline display of primary actions -->
@for (a of actions; track a.action) {
@if (showExpanded && viewContext?.isDialog && a.primaryAction) {
<button
mat-stroked-button
(click)="executeAction(a)"
*appDisabledEntityOperation="{
operation: a.permission,
entity: entity,
}"
angulartics2On="click"
[angularticsCategory]="entity?.getType()"
[angularticsAction]="'entity_' + a.action"
[matTooltip]="a.tooltip"
>
<fa-icon
class="standard-icon-with-text color-accent"
[icon]="a.icon"
></fa-icon>
<span>{{ a.label }}</span>
</button>
}
}
<!-- context menu -->
<button
mat-icon-button
color="primary"
style="margin-top: -8px; margin-bottom: -8px"
[matMenuTriggerFor]="additional"
>
<fa-icon icon="ellipsis-v" class="standard-icon"></fa-icon>
</button>
<!-- context menu -->
<mat-menu #additional>
<!-- standard actions -->
@for (a of actions; track a.action) {
@if (!a.primaryAction || !showExpanded || !viewContext?.isDialog) {
<button
mat-menu-item
(click)="executeAction(a)"
*appDisabledEntityOperation="{
operation: a.permission,
entity: entity,
}"
angulartics2On="click"
[angularticsCategory]="entity?.getType()"
[angularticsAction]="'entity_' + a.action"
[matTooltip]="a.tooltip"
matTooltipPosition="before"
>
<fa-icon
class="standard-icon-with-text color-accent"
[icon]="a.icon"
></fa-icon>
<span>{{ a.label }}</span>
</button>
}
}
<!-- additional actions -->
<ng-content></ng-content>
</mat-menu>
}
./entity-actions-menu.component.scss
:host {
display: flex;
align-items: center;
}