From 11de44b613281370c22304e3b99f7e47596efc3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ren=C3=A9=20Schultz=20Madsen?= Date: Sun, 18 Oct 2026 16:14:15 +0200 Subject: [PATCH] fix(cases): break the EformCasesModule import cycle in case-edit components CaseEditElementComponent and CaseEditNavComponent listed EformCasesModule in their standalone `imports`, while EformCasesModule imports and exports those same components. In the production bundle the module class is defined after the components, so their eager `dependencies` arrays held `undefined`. At runtime Angular threw NG0919 ("Cannot read @Directive metadata ... runtime circular dependency") and app-case-edit-element never rendered, e.g. in the case-complete modal. Both components only needed the module to render themselves recursively. A standalone component can already use its own selector, so the module import is removed and nothing replaces it. CaseEditSwitchComponent <-> ElementContainerComponent is a direct cycle of the same kind: the bundle defined the switch before the container, so the switch's dependency list captured `undefined` for element-container. Both sides now import each other through forwardRef, so the compiler emits a lazy `dependencies: () => [...]` closure that works whichever order the bundler picks. Co-Authored-By: Claude Opus 5.5 --- .../components/case-edit-nav/case-edit-nav.component.ts | 3 +-- .../case-edit-element/case-edit-element.component.ts | 3 +-- .../case-edit-switch/case-edit-switch.component.ts | 7 +++++-- .../element-container/element-container.component.ts | 6 ++++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/eform-client/src/app/common/modules/eform-cases/components/case-edit-nav/case-edit-nav.component.ts b/eform-client/src/app/common/modules/eform-cases/components/case-edit-nav/case-edit-nav.component.ts index 4527579e6a..9247f1ca95 100644 --- a/eform-client/src/app/common/modules/eform-cases/components/case-edit-nav/case-edit-nav.component.ts +++ b/eform-client/src/app/common/modules/eform-cases/components/case-edit-nav/case-edit-nav.component.ts @@ -1,12 +1,11 @@ import {Component, Input, OnInit} from '@angular/core'; import {ElementDto} from 'src/app/common/models'; import { NgFor, NgIf } from '@angular/common'; -import { EformCasesModule } from '../../eform-cases.module'; @Component({ selector: 'app-case-edit-nav', templateUrl: './case-edit-nav.component.html', - imports: [NgFor, NgIf, EformCasesModule] + imports: [NgFor, NgIf] }) export class CaseEditNavComponent implements OnInit { @Input() element: ElementDto = new ElementDto(); diff --git a/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-edit-element/case-edit-element.component.ts b/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-edit-element/case-edit-element.component.ts index 01a9f6bb29..64ed54c2d0 100644 --- a/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-edit-element/case-edit-element.component.ts +++ b/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-edit-element/case-edit-element.component.ts @@ -12,13 +12,12 @@ import { ReactiveFormsModule, FormsModule } from '@angular/forms'; import { CaseEditSwitchComponent } from '../case-edit-switch/case-edit-switch.component'; import { ElementCommentComponent } from '../case-elements/element-comment/element-comment.component'; import { ElementPictureComponent } from '../case-elements/element-picture/element-picture.component'; -import { EformCasesModule } from '../../../eform-cases.module'; import { TranslatePipe } from '@ngx-translate/core'; @Component({ selector: 'app-case-edit-element', templateUrl: './case-edit-element.component.html', - imports: [NgIf, MatRadioGroup, ReactiveFormsModule, FormsModule, MatRadioButton, CaseEditSwitchComponent, NgFor, ElementCommentComponent, ElementPictureComponent, EformCasesModule, TranslatePipe] + imports: [NgIf, MatRadioGroup, ReactiveFormsModule, FormsModule, MatRadioButton, CaseEditSwitchComponent, NgFor, ElementCommentComponent, ElementPictureComponent, TranslatePipe] }) export class CaseEditElementComponent implements OnInit { @ViewChildren(CaseEditElementComponent) editElements: QueryList; diff --git a/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-edit-switch/case-edit-switch.component.ts b/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-edit-switch/case-edit-switch.component.ts index 4773645d67..6ba2bd0c90 100644 --- a/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-edit-switch/case-edit-switch.component.ts +++ b/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-edit-switch/case-edit-switch.component.ts @@ -1,4 +1,4 @@ -import {Component, EventEmitter, Input, OnInit, Output} from '@angular/core'; +import {Component, EventEmitter, forwardRef, Input, OnInit, Output} from '@angular/core'; import {DataItemDto} from 'src/app/common/models'; import { NgIf, NgFor, NgSwitch, NgSwitchCase, NgSwitchDefault } from '@angular/common'; import { ElementPictureComponent } from '../case-elements/element-picture/element-picture.component'; @@ -22,7 +22,10 @@ import { ElementAudioComponent } from '../case-elements/element-audio/element-au @Component({ selector: 'app-case-edit-switch', templateUrl: './case-edit-switch.component.html', - imports: [NgIf, NgFor, NgSwitch, NgSwitchCase, ElementPictureComponent, ElementCheckboxComponent, ElementNumberComponent, ElementNumberStepperComponent, ElementCommentComponent, ElementTextComponent, ElementDateComponent, ElementSingleselectComponent, ElementMultiselectComponent, ElementPdfComponent, ElementInfoboxComponent, ElementTimerComponent, ElementSignatureComponent, ElementContainerComponent, ElementEntitysearchComponent, ElementEntityselectComponent, ElementAudioComponent, NgSwitchDefault] + imports: [NgIf, NgFor, NgSwitch, NgSwitchCase, ElementPictureComponent, ElementCheckboxComponent, ElementNumberComponent, ElementNumberStepperComponent, ElementCommentComponent, ElementTextComponent, ElementDateComponent, ElementSingleselectComponent, ElementMultiselectComponent, ElementPdfComponent, ElementInfoboxComponent, ElementTimerComponent, ElementSignatureComponent, + // ElementContainerComponent imports this component back; forwardRef makes the + // compiler emit a lazy dependency list so neither side captures `undefined`. + forwardRef(() => ElementContainerComponent), ElementEntitysearchComponent, ElementEntityselectComponent, ElementAudioComponent, NgSwitchDefault] }) export class CaseEditSwitchComponent implements OnInit { @Input() dataItemList: Array = []; diff --git a/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-elements/element-container/element-container.component.ts b/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-elements/element-container/element-container.component.ts index f91a047b28..52f12500b4 100644 --- a/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-elements/element-container/element-container.component.ts +++ b/eform-client/src/app/common/modules/eform-cases/components/case-edit/case-elements/element-container/element-container.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output} from '@angular/core'; +import { Component, EventEmitter, forwardRef, Input, Output} from '@angular/core'; import { DataItemDto } from 'src/app/common/models'; import { MatCard, MatCardHeader, MatCardContent } from '@angular/material/card'; import { MatIcon } from '@angular/material/icon'; @@ -10,7 +10,9 @@ import { CaseEditSwitchComponent } from '../../case-edit-switch/case-edit-switch selector: 'element-container', templateUrl: './element-container.component.html', styleUrls: ['./element-container.component.scss'], - imports: [MatCard, MatCardHeader, MatIcon, MatCardContent, NgClass, CaseEditSwitchComponent] + imports: [MatCard, MatCardHeader, MatIcon, MatCardContent, NgClass, + // CaseEditSwitchComponent imports this component back (runtime cycle). + forwardRef(() => CaseEditSwitchComponent)] }) export class ElementContainerComponent { dataItemList: Array = [];