import { EntityForm } from "#src/app/core/common-components/entity-form/entity-form";
import { EntityFieldEditComponent } from "#src/app/core/entity/entity-field-edit/entity-field-edit.component";
import {
Component,
DestroyRef,
inject,
OnInit,
ChangeDetectionStrategy,
} from "@angular/core";
import {
FormControl,
FormsModule,
ReactiveFormsModule,
Validators,
} from "@angular/forms";
import { MatButtonModule } from "@angular/material/button";
import {
MAT_DIALOG_DATA,
MatDialogModule,
MatDialogRef,
} from "@angular/material/dialog";
import { MatFormFieldModule } from "@angular/material/form-field";
import { MatInputModule } from "@angular/material/input";
import { MatTooltipModule } from "@angular/material/tooltip";
import { FontAwesomeModule } from "@fortawesome/angular-fontawesome";
import { DialogCloseComponent } from "app/core/common-components/dialog-close/dialog-close.component";
import { EntityFormService } from "app/core/common-components/entity-form/entity-form.service";
import { FormFieldConfig } from "app/core/common-components/entity-form/FormConfig";
import { Entity, EntityConstructor } from "../../model/entity";
import { EntityFieldSelectComponent } from "#src/app/core/entity/entity-field-select/entity-field-select.component";
@Component({
changeDetection: ChangeDetectionStrategy.OnPush,
selector: "app-entity-bulk-edit",
imports: [
MatDialogModule,
MatButtonModule,
DialogCloseComponent,
MatInputModule,
FormsModule,
ReactiveFormsModule,
FontAwesomeModule,
MatTooltipModule,
MatFormFieldModule,
EntityFieldEditComponent,
EntityFieldSelectComponent,
],
templateUrl: "./entity-bulk-edit.component.html",
styleUrl: "./entity-bulk-edit.component.scss",
})
export class EntityBulkEditComponent<E extends Entity> implements OnInit {
private dialogRef = inject<MatDialogRef<any>>(MatDialogRef);
private entityFormService = inject(EntityFormService);
private readonly destroyRef = inject(DestroyRef);
entityConstructor: EntityConstructor;
entitiesToEdit: E[];
selectedFieldFormControl: FormControl;
fieldValueForm: EntityForm<E>;
entityData: E;
showValueForm: boolean = false;
selectedField: FormFieldConfig;
constructor() {
const data = inject<{
entitiesToEdit: E[];
entityConstructor: EntityConstructor;
}>(MAT_DIALOG_DATA);
this.entityConstructor = data.entityConstructor;
this.entityData = data.entitiesToEdit[0];
this.entitiesToEdit = data.entitiesToEdit;
}
ngOnInit(): void {
this.initForm();
// The bulk-edit form's unsaved-changes state is tracked per-form and cleared
// automatically when this dialog (and thus its DestroyRef) is destroyed.
}
private initForm() {
this.selectedFieldFormControl = new FormControl("", Validators.required);
this.selectedFieldFormControl.valueChanges.subscribe(
async (fieldId: string) => {
if (!fieldId) return;
this.selectedField = this.entityFormService.extendFormFieldConfig(
{ id: fieldId },
this.entityConstructor,
);
await this.createEntityForm([fieldId]);
this.showValueForm = true;
},
);
}
private async createEntityForm(fieldKeys: string[]) {
this.fieldValueForm = await this.entityFormService.createEntityForm(
fieldKeys,
this.entityData,
this.destroyRef,
);
const selectedField = this.selectedFieldFormControl.value;
if (this.fieldValueForm.formGroup.controls[selectedField]) {
this.fieldValueForm.formGroup.controls[selectedField].setValue("");
}
}
save() {
this.selectedFieldFormControl.markAsTouched();
if (this.selectedFieldFormControl.invalid) return;
const selectedField = this.selectedFieldFormControl.value;
const value =
this.fieldValueForm?.formGroup.controls[selectedField]?.value || "";
const returnValue: BulkEditAction = {
selectedField,
value,
};
this.dialogRef.close(returnValue);
}
}
export interface BulkEditAction {
selectedField: string;
value: any;
}
<h2 mat-dialog-title i18n>
Bulk edit {{ entitiesToEdit.length }} {{ entityConstructor.labelPlural }}
</h2>
<app-dialog-close mat-dialog-close></app-dialog-close>
<mat-dialog-content>
<p i18n>
You are about to modify the selected records. This action will apply changes
across multiple entries. Make sure that the fields you are updating reflect
the correct information for all selected records.<br />
If you are unsure about making changes across all these records, review your
selection carefully before proceeding or edit the records individually.
</p>
<form>
<div class="entity-form-cell">
<mat-form-field appearance="fill">
<mat-label i18n>Property to update</mat-label>
<app-entity-field-select
[formControl]="selectedFieldFormControl"
[multi]="false"
[entityType]="entityConstructor"
>
</app-entity-field-select>
</mat-form-field>
</div>
@if (showValueForm) {
<div class="entity-form-cell">
<app-entity-field-edit
[field]="selectedField"
[entity]="entityData"
[form]="fieldValueForm"
></app-entity-field-edit>
</div>
}
</form>
</mat-dialog-content>
<mat-dialog-actions>
<button mat-button (click)="save()" i18n="Button label">Save</button>
<button mat-button mat-dialog-close i18n="Button label">Cancel</button>
</mat-dialog-actions>