Search code examples
angularcircular-dependencyuncaught-reference-error

Angular: ReferenceError: Cannot access 'FixedDeposit' before initialization + Circular Dependency Warning


I have went through the below SO Question for a solution:

Angular: 7.2.1 ES6 class ReferenceError : Cannot access 'X' before initialization

Firstly, I'm getting the below warnings on my VS Code terminal:

WARNING in Circular dependency detected: src\app\modules\asset-classes\fixed-income\fixed-deposits\components\fixed-deposits-details\fixed-deposits-details.component.ts -> src\app\modules\asset-classes\fixed-income\fixed-deposits\components\fixed-deposits-form\fixed-deposits-form.component.ts -> src\app\modules\asset-classes\fixed-income\fixed-deposits\components\fixed-deposits-details\fixed-deposits-details.component.ts

WARNING in Circular dependency detected: src\app\modules\asset-classes\fixed-income\fixed-deposits\components\fixed-deposits-form\fixed-deposits-form.component.ts -> src\app\modules\asset-classes\fixed-income\fixed-deposits\components\fixed-deposits-details\fixed-deposits-details.component.ts -> src\app\modules\asset-classes\fixed-income\fixed-deposits\components\fixed-deposits-form\fixed-deposits-form.component.ts

WARNING in Circular dependency detected: src\app\modules\shared\components\common-dialog\common-dialog.component.ts -> src\app\view-manager.service.ts -> src\app\modules\shared\components\common-dialog\common-dialog.component.ts

WARNING in Circular dependency detected: src\app\view-manager.service.ts -> src\app\modules\shared\components\common-dialog\common-dialog.component.ts -> src\app\view-manager.service.ts

Now, that obviously because of the below code in my respective components:

fixed-deposits-form.component.ts

On Save click >>

this.viewService.loadSideNavWithCallback(
    FixedDepositsDetailsComponent,
    (compRef: ComponentRef<any>) => {
    compRef.instance.fixedDeposit = fixedDepositEntity;
});

fixed-deposits-details.component.ts

On Edit click >>

this.viewService.loadSideNavWithCallback(
  FixedDepositsFormComponent,
  (compRef: ComponentRef<any>) => {
    compRef.instance.fixedDeposit = this.fixedDeposit;
  });

The viewService is basically my ViewManagerService that helps achieved loose coupling between angular components and also serves for view navigation. Since the FixedDepositsFormsComponent & FixedDepositsDetailsComponent open in a side-nav (which is present on the AppComponent), the ViewManagerService does the job of load those components.

Although it is pretty obvious that I have a circular dependency, I don't know how to fix it.

Also I'm getting the below error in my browser console:

Uncaught ReferenceError: Cannot access 'FixedDeposit' before initialization at Module.FixedDeposit (main.js:4274) at Module../src/app/modules/asset-classes/fixed-income/fixed-deposits/components/fixed-deposits-details/fixed-deposits-details.component.ts (fixed-deposits-details.component.ts:21)

Now the line no.21 simply points to my @Input property on the details component:

export class FixedDepositsDetailsComponent implements OnInit {

  @Input() fixedDeposit: FixedDeposit;

If I remove the loadSideNavWithCallback code (called on save click) from my FixedDepositsFormComponent, there's no error. But I cannot do away with it since I need to have that code to load the details component.

Appreciate any help in advance.


Solution

  • Cyclic dependencies are bad because it makes it impossible for webpack to initialize modules in dependency order. Normally webpack ensures that whenever a module's export is imported elsewhere, the exporting module executes before the importing one, thereby ensuring that all values are defined and initialized before they are imported elsewhere.

    However, if circular dependencies exist, no such initialization order exists, making it possible that a value is imported before it is defined, which causes the import to return undefined. Because this is surprising and can be hard to debug, Angular CLI emits a warning if circular dependencies are detected. And well it did, because it hints how your FixedDeposit came to be used before its initialization.

    It is therefore a good idea to heed the CLI's warning and avoid creating circular dependencies in your code.

    The viewService is basically my ViewManagerService that helps achieved loose coupling between angular components and also serves for view navigation

    As we have seen, your "loose" coupling is still too tight. Moreover, using a stateful service for navigation bypasses the angular router, making it impossible for users to bookmark individual views, and causes live reloads during development to fall back to a different view.

    For all of these reasons, navigation should be performed using the angular router rather than a stateful service. Then, a component can navigate to a different view without knowing the component responsible for this view, and thus without creating a circular dependency among component classes. Further information on how to configure and use the angular router is available in the official angular tutorial.