|
entity
|
Type : E
|
|
Required : true
|
|
|
Methods
|
close
|
close(result?: any)
|
|
|
Parameters :
| Name |
Type |
Optional |
| result |
any
|
Yes
|
|
|
onAction
|
onAction(action: string)
|
|
|
Parameters :
| Name |
Type |
Optional |
| action |
string
|
No
|
|
|
detailsRoute
|
Type : unknown
|
Default value : computed(() => {
const entity = this.entity();
if (entity.isNew) {
return undefined;
}
const route = getEntityRuntimeRoute(entity.getConstructor());
const detailsPath = `${route.replace(/^\//, "")}/:id`;
if (route && this.router.config.some((r) => r.path === detailsPath)) {
return route + "/" + entity.getId(true);
}
return undefined;
})
|
|
|
|
Protected
viewContext
|
Type : unknown
|
Default value : inject(ViewComponentContext, { optional: true })
|
|
|
import {
Component,
inject,
ChangeDetectionStrategy,
input,
output,
computed,
effect,
} from "@angular/core";
import { MatButtonModule } from "@angular/material/button";
import { Angulartics2Module } from "angulartics2";
import { MatDialogModule, MatDialogRef } from "@angular/material/dialog";
import { Entity } from "../../entity/model/entity";
import { InvalidFormFieldError } from "../../common-components/entity-form/invalid-form-field.error";
import { EntityFormService } from "../../common-components/entity-form/entity-form.service";
import { EntityForm } from "#src/app/core/common-components/entity-form/entity-form";
import { AlertService } from "../../alerts/alert.service";
import { MatMenuModule } from "@angular/material/menu";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { Router, RouterLink } from "@angular/router";
import { EntityAbility } from "../../permissions/ability/entity-ability";
import { UnsavedChangesService } from "../../entity-details/form/unsaved-changes.service";
import { EntityActionsMenuComponent } from "../../entity-details/entity-actions-menu/entity-actions-menu.component";
import { ViewComponentContext } from "../../ui/abstract-view/view-component-context";
import { getEntityRuntimeRoute } from "../../entity/entity-config.service";
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-dialog-buttons",
imports: [
MatButtonModule,
Angulartics2Module,
MatDialogModule,
MatMenuModule,
FontAwesomeModule,
RouterLink,
EntityActionsMenuComponent,
],
templateUrl: "./dialog-buttons.component.html",
styleUrls: ["./dialog-buttons.component.scss"],
})
export class DialogButtonsComponent<E extends Entity> {
private entityFormService = inject(EntityFormService);
private dialog = inject<MatDialogRef<any>>(MatDialogRef, { optional: true });
private alertService = inject(AlertService);
private router = inject(Router);
private ability = inject(EntityAbility);
private unsavedChanges = inject(UnsavedChangesService);
protected viewContext = inject(ViewComponentContext, { optional: true });
entity = input.required<E>();
form = input.required<EntityForm<E>>();
closeView = output<any>();
detailsRoute = computed(() => {
const entity = this.entity();
if (entity.isNew) {
return undefined;
}
const route = getEntityRuntimeRoute(entity.getConstructor());
const detailsPath = `${route.replace(/^\//, "")}/:id`;
if (route && this.router.config.some((r) => r.path === detailsPath)) {
return route + "/" + entity.getId(true);
}
return undefined;
});
constructor() {
if (this.dialog) {
this.initDialogSettings();
}
// Handle permissions check when entity changes
effect(() => {
const entity = this.entity();
const form = this.form();
if (!entity.isNew) {
if (this.ability.cannot("update", entity)) {
form.formGroup.disable();
}
}
});
}
private initDialogSettings() {
this.dialog.disableClose = true;
this.dialog.backdropClick().subscribe(() =>
// only consider this dialog's own form, so a dirty view underneath the dialog
// does not trigger a discard prompt for changes unrelated to this dialog
this.unsavedChanges.checkUnsavedChanges(this.form()).then((confirmed) => {
if (confirmed) {
this.dialog.close();
}
}),
);
}
async save() {
this.entityFormService
.saveChanges(this.form(), this.entity())
.then((res) => {
// Attachments are only saved once form is disabled
this.form().formGroup.disable();
this.form().formGroup.markAsPristine();
this.close(res);
})
.catch((err) => {
if (!(err instanceof InvalidFormFieldError)) {
this.alertService.addDanger(err.message);
}
});
}
cancel() {
// discard this form's unsaved changes
this.unsavedChanges.setUnsavedChanges(this.form(), false);
this.close();
}
close(result?: any) {
this.dialog?.close(result);
this.closeView.emit(result);
}
onAction(action: string) {
if (action === "delete") {
this.close();
}
}
}
<button
mat-raised-button
color="accent"
(click)="save()"
angulartics2On="click"
[angularticsCategory]="entity()?.getType()"
angularticsAction="form_popup_save"
i18n="Form save button"
>
Save
</button>
@if (viewContext?.isDialog) {
<button
mat-stroked-button
(click)="cancel()"
angulartics2On="click"
[angularticsCategory]="entity()?.getType()"
angularticsAction="form_popup_cancel"
i18n="Form cancel button"
>
Cancel
</button>
}
@if (detailsRoute() && viewContext?.isDialog) {
<button
mat-raised-button
[routerLink]="detailsRoute()"
mat-dialog-close
[disabled]="form().formGroup.disabled"
i18n="Form button to navigate to details page of entity"
>
Go to details
</button>
}
<!-- inline content projected immediately before the context menu (e.g. the
change-history button), so it sits right next to the "⋮" trigger -->
<ng-content select="[beforeContextMenu]"></ng-content>
<app-entity-actions-menu
[entity]="entity()"
(actionTriggered)="onAction($event)"
>
<ng-content></ng-content>
</app-entity-actions-menu>
:host {
display: flex;
align-items: center;
}
Legend
Html element with directive