From 48f2167c8ef9d097d582c3eb4e6ed6ac67c2575f Mon Sep 17 00:00:00 2001 From: Algirdas Date: Sun, 5 Jul 2026 00:20:52 +0300 Subject: [PATCH] fix(frontend): defer review list mutation to avoid NG0100 - close expense dialog with a signal instead of mutating list inside close callback - defer removeExpenseFromList via setTimeout so it runs after change detection - centralize empty-close in removeExpenseFromList --- .../statement-review-dialog.component.ts | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/frontend/src/app/modules/main/dialogs/statement-review-dialog/statement-review-dialog.component.ts b/frontend/src/app/modules/main/dialogs/statement-review-dialog/statement-review-dialog.component.ts index ab5404d..a3203fe 100644 --- a/frontend/src/app/modules/main/dialogs/statement-review-dialog/statement-review-dialog.component.ts +++ b/frontend/src/app/modules/main/dialogs/statement-review-dialog/statement-review-dialog.component.ts @@ -58,21 +58,23 @@ export class StatementReviewDialogComponent implements OnInit { showBalanceTab: false, deletable: true, onExpenseDelete: () => { - this.removeExpenseFromList(expense); - expenseDialog.close(); - this.closeIfEmpty(); + expenseDialog.close(true); }, }, }); expenseDialog.onClose.subscribe((result: Expense | boolean | undefined) => { - if (!(result instanceof Expense)) { + if (!result) { return; } - this.removeExpenseFromList(expense); - this.calendarRefreshNeeded = true; - this.closeIfEmpty(); + if (result instanceof Expense) { + this.calendarRefreshNeeded = true; + } + + // Defer list mutation to the next tick so it does not run inside + // the same change detection cycle that is closing the dialog. + setTimeout(() => this.removeExpenseFromList(expense)); }); } @@ -128,6 +130,7 @@ export class StatementReviewDialogComponent implements OnInit { this.reloadGroupedExpenses(); this.onImportChange([...this.expenses]); + this.closeIfEmpty(); } private reloadGroupedExpenses(): void {