Description
A simple wrapper function of the EntityFormComponent which can be used as a dynamic component
e.g. as a panel for the EntityDetailsComponent.
Example
|
creatingNew
|
Type : boolean
|
Default value : false
|
|
|
Methods
|
cancelClicked
|
cancelClicked()
|
|
|
|
|
|
Async
saveClicked
|
saveClicked()
|
|
|
|
|
|
Readonly
form
|
Type : unknown
|
Default value : this.formResource.value
|
|
|
import {
ChangeDetectionStrategy,
Component,
DestroyRef,
effect,
inject,
input,
resource,
} from "@angular/core";
import { Entity } from "../../entity/model/entity";
import { getParentUrl } from "../../../utils/utils";
import { Router } from "@angular/router";
import { Location } from "@angular/common";
import { DynamicComponent } from "../../config/dynamic-components/dynamic-component.decorator";
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 { MatButtonModule } from "@angular/material/button";
import { EntityFormComponent } from "../../common-components/entity-form/entity-form/entity-form.component";
import { DisableEntityOperationDirective } from "../../permissions/permission-directive/disable-entity-operation.directive";
import { FieldGroup } from "./field-group";
import { ViewComponentContext } from "../../ui/abstract-view/view-component-context";
import { PublicFormConfig } from "../../../features/public-form/public-form-config";
import { PublicFormPermissionService } from "../../../features/public-form/public-form-permission.service";
/**
* A simple wrapper function of the EntityFormComponent which can be used as a dynamic component
* e.g. as a panel for the EntityDetailsComponent.
*/
@DynamicComponent("Form")
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-form",
templateUrl: "./form.component.html",
styleUrls: ["./form.component.scss"],
imports: [
MatButtonModule,
EntityFormComponent,
DisableEntityOperationDirective,
],
})
export class FormComponent<E extends Entity> {
private router = inject(Router);
private location = inject(Location);
private entityFormService = inject(EntityFormService);
private alertService = inject(AlertService);
private viewContext = inject(ViewComponentContext, { optional: true });
private readonly permissionService = inject(PublicFormPermissionService);
private readonly destroyRef = inject(DestroyRef);
entity = input<E>();
creatingNew = input<boolean>(false);
fieldGroups = input<FieldGroup[]>();
private readonly formResource = resource({
params: () => ({ entity: this.entity(), fieldGroups: this.fieldGroups() }),
loader: async ({ params: { entity, fieldGroups } }) => {
if (!entity || !fieldGroups) return undefined;
return this.entityFormService.createEntityForm(
[].concat(...fieldGroups.map((group) => group.fields)),
entity,
this.destroyRef,
);
},
});
readonly form = this.formResource.value;
constructor() {
effect(() => {
const form = this.form();
if (form && !this.creatingNew()) {
form.formGroup.disable();
}
});
}
async saveClicked() {
const entity = this.entity();
const form = this.form();
if (!entity || !form) {
return;
}
try {
// Check if this is a PublicFormConfig and needs permission checking
if (entity.getType() === PublicFormConfig.ENTITY_TYPE) {
const entityType = form.formGroup.getRawValue()["entity"] as string;
if (!(await this.permissionService.checkOnSave(entityType))) return;
}
await this.entityFormService.saveChanges(form, entity);
if (this.creatingNew() && !this.viewContext?.isDialog) {
await this.router.navigate([
getParentUrl(this.router),
entity.getId(true),
]);
}
} catch (err) {
if (!(err instanceof InvalidFormFieldError)) {
this.alertService.addDanger(err.message);
}
}
}
cancelClicked() {
const entity = this.entity();
const form = this.form();
if (!entity || !form) {
return;
}
if (this.creatingNew()) {
this.location.back();
return;
}
this.entityFormService.resetForm(form, entity);
form.formGroup.disable();
}
}
/**
* Config format that the FormComponent handles.
*/
export interface FormConfig {
fieldGroups: FieldGroup[];
}
<div
class="form-buttons-wrapper padding-bottom-small flex-row gap-small align-self-end"
>
@if (form()?.formGroup.enabled) {
<button
mat-raised-button
color="accent"
(click)="saveClicked()"
i18n="Save button for forms"
>
Save
</button>
<button
mat-stroked-button
(click)="cancelClicked()"
i18n="Cancel button for forms"
>
Cancel
</button>
}
@if (form()?.formGroup.disabled && !entity()?.anonymized) {
<button
mat-raised-button
(click)="form()?.formGroup.enable()"
*appDisabledEntityOperation="{
entity: entity(),
operation: 'update',
}"
i18n="Edit button for forms"
>
Edit
</button>
}
</div>
@if (form()) {
<app-entity-form
[entity]="entity()"
[fieldGroups]="fieldGroups()"
[form]="form()"
></app-entity-form>
}
@use "variables/sizes";
@use "variables/colors";
:host {
display: flex;
flex-direction: column;
}
.form-buttons-wrapper {
position: sticky;
top: sizes.$regular;
z-index: 100;
margin-right: 3px;
background-color: colors.$background;
padding: sizes.$x-small;
}
Legend
Html element with directive