WARNING in Circular dependency detected - Angular Cli
Asked Answered
S

5

34

https://github.com/angular/angular-cli/pull/6813 Added warnings for circular dependencies, and I know I can turn off all warnings using "showCircularDependencies": false. But I would rather keep the circular dependency warnings on. Is there a pattern that will let me fix the use case below, or is there a way to specifically disable the circular dependency plugin on a particular file?

The simplest scenario is if I have 3 files:

forms.model.ts

import { CustomModel } from './custom.model';
import { CustomForm } from './custom.form';

export class Forms {
  items: CustomForm[] = [];
  public constructor(models?: CustomModel[]) {
    models.forEach(model => this.items.push(new CustomForm(model)));
  }
}

custom.model.ts

export class CustomModel {
  nestedModels: CustomModel[];    
}

custom.form.ts

import { Forms } from './forms.model';
import { CustomModel } from './custom.model';

export class CustomForm {
  nestedForms: Forms;

  constructor(model: CustomModel) {
    this.nestedForms = new Forms(model.nestedModels);
  }
}

This causes the following warnings:

WARNING in Circular dependency detected:
src\app\models\custom.form.ts -> src\app\models\forms.model.ts -> src\app\models\custom.form.ts

WARNING in Circular dependency detected:
src\app\models\forms.model.ts -> src\app\models\custom.form.ts -> src\app\models\forms.model.ts

In my actual app there are about 20-30 warnings because of this same pattern. I think the underlying plugin https://github.com/aackerman/circular-dependency-plugin supports exclude patterns, but i'm not sure if theres a way to use this via the angular-cli.

Sokil answered 24/11, 2017 at 3:56 Comment(1)
Check this github.com/angular/angular-cli/issues/7705Rope
R
35

The issue is clear :

You are using custom.model.ts into custom.form.ts

and also custom.form.ts into custom.model.ts,

This is called CircularDependencies and that is not good.

Solution :

Just remove import { CustomForm } from './custom.form'; from custom.model.ts

Rutharuthann answered 24/11, 2017 at 4:4 Comment(4)
Ah sorry, that import was by accident when creating this SO question. I've edited that line out of the original question now. Removing the import doesn't help in this case. The circular dependency is caused by the calls to new Forms() and new CustomForms().Sokil
custom.form.ts wasn't imported into custom.model.ts.Circumcise
Can you explain why a circular dependency is 'not good'? I can have a two functions in one file, where each function can in certain circumstances call the other. This is also a circular dependency (each function needs the other to exist), but I've not seen a modern compiler complain about this case...Encapsulate
I got myself into a similar situation and what I did to fix was to create an external shared module declaring all shared components and defining exported components, and then importing them at consuming modules. This tut vid helped me understood better youtube.com/watch?v=p2Bvtv5PUJ0Electrokinetic
P
8

You can have the code of forms.model.ts and custom.form.ts in the same file and that will remove the circular dependency.

Puffer answered 24/11, 2017 at 5:22 Comment(1)
This is what Angular Material components library does for it's Stepper and Step classes, because they reference each other.Charlean
C
3

The forms.model.ts uses custom.form.ts, custom.form.ts uses forms.model.ts this is the cause of the dependency cycle, remove this relation by changing your model.

How do you create Forms when you don't have a CustomForm, and you cannot create CustomForm, because you don't have Forms? (Yes, you can use null or undefined but this is ugly)

forms.model.ts

import { CustomModel } from './custom.model';
import { CustomForm } from './custom.form';

export class Forms {
  items: CustomForm[] = []; /** refences to CustomForm **/
  public constructor(models?: CustomModel[]) {
    models.forEach(model => this.items.push(new CustomForm(model)));
  }
}

custom.form.ts

import { Forms } from './forms.model';
import { CustomModel } from './custom.model';

export class CustomForm {
  nestedForms: Forms; /** refences to Forms **/

  constructor(model: CustomModel) {
    this.nestedForms = new Forms(model.nestedModels);
  }
}
Curtain answered 4/7, 2018 at 12:58 Comment(0)
R
3

I'd like to add to this conversation that if you have circular dependency warnings and it isnt caused by imports from a barrel file that somehow cross reference each other, it might be provideIn: root that causes the circular dependency warning.

@Injectable({provideIn: root}) This made one of my services get provided either twice or provided in a file it shouldn't be while compiling.

Raseda answered 4/8, 2021 at 12:20 Comment(0)
I
-2

You can also hide these circular CI warnings by adding the following line in your angular.json file

            "build": {
                "options": {
                    .....,
                    "showCircularDependencies": false
                },
                "configurations": {
                ....
                }
            },
            "serve": {
                ....
            },
        }```
Inwards answered 26/4, 2021 at 9:44 Comment(1)
Completely agree with @srikanth_yarram, never provide someone advise to suppress these kind of warnings. This is a potential problem in the design and should advise them to fix it.Mikelmikell

© 2022 - 2024 — McMap. All rights reserved.