Dhanusha_Perera07
Dhanusha_Perera07

Reputation: 4584

"Circular dependency detected" warning - Angular

This is the warning I get in the web browser. I would like to know the reason and how to fix it.

client:135 Circular dependency detected: src\app\employee\employee.component.ts -> src\app\shared\service\employee.service.ts -> src\app\employee\employee.component.ts

Circular dependency detected waring displayed in the browser

Here is my employee.component.ts file.

import {Component, OnInit} from '@angular/core';
import {EmployeeService} from '../shared/service/employee.service';
import {Employee} from '../shared/model/employee/employee.model';

@Component({
  selector: 'app-employee',
  templateUrl: './employee.component.html',
  styleUrls: ['./employee.component.scss']
})
export class EmployeeComponent implements OnInit {

  activeEmployee: Employee;

  constructor(private employeeService: EmployeeService) {
    this.activeEmployee = this.employeeService.getActiveEmployee();
  }

  ngOnInit(): void {
  }

  closeDialog(): void {
    // this.employeeService.dialogRef.close();
    this.employeeService.closeDialogBox();
  }
}

Here is my employee.service.ts file.

import {Injectable} from '@angular/core';
import {Employee} from '../model/employee/employee.model';
import {MatDialog, MatDialogConfig, MatDialogRef} from '@angular/material/dialog';
import {EmployeeComponent} from '../../employee/employee.component';
import {Position} from '../model/employee/position.enum';
import {Status} from '../model/employee/status.enum';
import {Gender} from '../model/gender.enum';

const employeeSample = new Employee(2,
  'John Doe',
  '22, Sample Road, Sample 03',
  new Date(Date.parse('01/01/1995')),
  'XXXXXXXXX',
  '94-XXXXXXXX',
  '[email protected]',
  Gender.MALE,
  Position.INTERN,
  Status.ACTIVE,
  null // password
);

@Injectable({
  providedIn: 'root'
})
export class EmployeeService {

  activeEmployee = employeeSample;
  dialogConfig: MatDialogConfig = new MatDialogConfig();
  dialogRef!: MatDialogRef<any>;

  constructor(public dialog: MatDialog
  ) {
    this.dialogConfig = {
      width: '60%',
      height: '100%',
      disableClose: true
    };
  }

  openDialogBox(): void {
    this.dialogRef = this.dialog.open(EmployeeComponent, this.dialogConfig);
  }

  closeDialogBox(): void{
    this.dialogRef.close();
  }

  getActiveEmployee(): Employee{
    return this.activeEmployee;
  }

}

Upvotes: 3

Views: 10674

Answers (6)

JulienCC
JulienCC

Reputation: 528

For someone coming from C++ like I do this is weird. You have to understand that the way files and namespaces work in Javascript is REALLY different from C++ (and some other languages).

In C++ you can have a class in a namespace in a file, and an other class in the same namespace in an other file, and this is fine :

  • file A
    • include class B headers
    • namespace X
      • class A (uses B)
  • file B
    • include class A headers
    • namespace X
      • class B (uses A)

But in Javascript you have to proceed this way :

  • file A
    • import class B directly
    • export class A (uses B)
  • file B
    • !!! YOU CAN'T import class A
    • class B (can't use A)
  • file X (the file is the namespace)
    • import class A
    • import class B
    • export class A
    • export class B

I didn't find any workaround yet. I guess you have to rely on some other code packing tools to put your interdependent classes in the same file. In the end in JS these files are "modules", which means what it means : a module is not a class file.

You should probably have your classes in different files then use some tool to pack all these files in a single JS module.

Of course sometime it is possible to organize your code in a way were you don't have two classes directly requiring each other.

Upvotes: 3

Sunny Goel
Sunny Goel

Reputation: 2132

This warning comes when you use code of one module in another and vice versa.

let say you have 2 modules you are using module A code in module B and also using module B code in module A. so in this scenario you will get Circular dependency Warning.

In your case you are injecting the Employee Service in the Employee Component and also using the Employee component in Employee Service so this usage gives you Circular warning.

also checkout this question, it is similar to your question.

for quick resolution you can do one thing i.e. pass a component parameter which you want to render in Dialog box to this function openDialogBox so in that case you don't need to import the Employee component in the service and it will resolve your issue.

Upvotes: 2

Salahuddin Ahmed
Salahuddin Ahmed

Reputation: 5650

This is because you are importing employee service in employee component and vice-versa. Component should be dependent in service but not the service should be dependent on the component. Service should only be responsible for data provider whereas component should be controller of UI. So, select the things in a sequence accordingly and hence you could avoid the circular dependency created here.

Upvotes: 1

Alvin Saldanha
Alvin Saldanha

Reputation: 916

That is because you are injecting the employee.service.ts in employee.component.ts and vice versa.

Ideally the service should not be controlling the UI components. That is the job of the component.ts. Service should ideally work with data transformation.

Move the openDialogBox() and closeDialogBox() methods into the employee.component.ts and remove the reference of the component from your service.

Upvotes: 6

samuei
samuei

Reputation: 2102

Line 4 of employee.service imports employee.component.

Line 2 of employee.component imports employee.service.

When you get to line 2 of the one, it loads the other. When it gets to line 4 of that, it loads the first, which loads the second, which loads the first. It's a circle, get it?

The real question is why you need to be calling each of them from the other. Choose one to be in charge and it can call the other.

Upvotes: 2

Anarno
Anarno

Reputation: 1640

The error says clearly what's happening. You trying to import A file into B file, but at the same time, you trying to import B file into A file. You have to keep a tree structure. If you really want to do this, simply lift up that functionality to another file, for example, move to C file, then import C file into B and A.

Upvotes: 2

Related Questions