Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I resolve this Angular 7 "Circular dependency detected" warning

In my Angular 7 project, I want to have a file "pages.ts" where I export the routes my app is going to have. These are imported by "app-routing.ts" to be used by the RouterModule, and also imported by "pages.service.ts" where I want to manage the data of those routes. Now, in one of my components "test-one.component.ts" I want to use that service "pages.service.ts" so I can get for example the data of a route by its path or title. Everything works properly but this warning appears.

WARNING in Circular dependency detected: src/app/pages/test-one/test-one.component.ts -> src/app/core/services/pages.service.ts -> src/app/core/constants/pages.ts -> src/app/pages/test-one/test-one.component.ts

"pages.ts"

import { Page } from '../../core/models/page.model';
import { LoginComponent } from '../../pages/login/login.component';
import { SignupComponent } from '../../pages/signup/signup.component';

export const routePages: Page[] = [
    {
        path: '',
        redirectTo: 'login',
        pathMatch: 'full'
    },
    {
        path: 'login',
        component: LoginComponent,
        canActivate: [],
        data: {
            title: 'Login',
            description: '',
            keywords: '',
            icon: 'fingerprint',
            hasBreadcrumb: true
        },
        pathMatch: 'full'
    },
    {
        path: 'sign-up',
        component: SignupComponent,
        canActivate: [],
        data: {
            title: 'Sign up',
            description: '',
            keywords: '',
            hasBreadcrumb: true
        },
        pathMatch: 'full'
    }
];

"app-routing.module.ts"

import { routePages } from './core/constants/pages';
import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';

@NgModule({
  imports: [RouterModule.forRoot(routePages, { scrollPositionRestoration: 'enabled' })],
  exports: [RouterModule]
})
export class AppRoutingModule { }

"pages.service.ts"

import { routePages } from './../constants/pages';
import { Page, PageData } from './../models/page.model';
import { Router } from '@angular/router';
import { Injectable, EventEmitter } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class PagesService {
  pages = routePages;
  private pagesChanged: EventEmitter<Page[]> = new EventEmitter<Page[]>();

  constructor(private location: Location, private router: Router) {
    this.setPagesFullPath();
    console.log(this.pages);
  }
.
.
.

}

"test-one.component.ts"

import { Page, PageData } from './../../core/models/page.model';
import { PagesService } from './../../core/services/pages.service';
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-test-one',
  templateUrl: './test-one.component.html',
  styleUrls: ['./test-one.component.scss']
})
export class TestOneComponent implements OnInit {
  testATwoPage: Page;

  constructor(private pagesService: PagesService) {
  }

  ngOnInit() {
    this.testATwoPage = this.pagesService.getPageByTitle('Test A two');
  }

}

I'd love to know how I could resolve this circular dependency without having to dispense with any functionalities.

Thanks in advance!

like image 733
Juan Luis López Avatar asked Mar 18 '20 12:03

Juan Luis López


People also ask

How do I fix warning in circular dependency detected?

To fix the error, we can either move the formula to another cell, or change the reference in the formula so that it refers to another cell. In this case we will change the cell reference to cell B1. As you can see in the image below, this adjustment has fixed the circular dependency error.

How do I stop circular dependency?

Avoiding circular dependencies by refactoring Circular dependencies create tight couplings between the classes or modules involved, which means both classes or modules have to be recompiled every time either of them is changed.

What is circular dependency warning?

A cyclic dependency exists when a dependency of a service directly or indirectly depends on the service itself. For example, if UserService depends on EmployeeService , which also depends on UserService . Angular will have to instantiate EmployeeService to create UserService , which depends on UserService , itself.

What causes circular dependency?

A circular dependency occurs when two classes depend on each other. For example, class A needs class B, and class B also needs class A. Circular dependencies can arise in Nest between modules and between providers. While circular dependencies should be avoided where possible, you can't always do so.


1 Answers

There is no one direct way around it. I understand your use-case though, and kinda support it. You should not have this kind of logic in your component. It should be done in a service. You are right about that. I'm not entirely sure it's the best idea to reuse the Routes export. It feels like you are better of using the Router.config property. Which should contain the entire route config:

@Injectable({
  providedIn: 'root'
})
export class PagesService {
  readonly pages: Routes = this.router.config;
  private pagesChanged: EventEmitter<Page[]> = new EventEmitter<Page[]>();

  constructor(private location: Location, private router: Router) {
    this.setPagesFullPath();
    console.log(this.pages);
  }
}

If this, for whatever reasons doesn't work. The way to get rid of circular dependencies is by splitting into multiple files. The main issue is your routePages. You can convert this to two files. One being pages.ts:

pages.ts

export enum PageRoute {
  Login: 'login',
  SignUp: 'sign-up'
}

export interface PageData {
  title: string;
  description: string;
  keywords: string;
  icon?: string;
  hasBreadcrumb: boolean;
}

export const PageRouteData: Record<PageRoute, PageData> {
  [AppPage.Login]: {
    title: 'Login',
    description: '',
    keywords: '',
    icon: 'fingerprint',
    hasBreadcrumb: true
  },
  [AppPage.SignUp]: {
    title: 'Sign up',
    description: '',
    keywords: '',
    hasBreadcrumb: true
  }
}

And another file which actually contains your routes which are digested by the router:

app.routes.ts

export const routePages: Page[] = [
  {
      path: '',
      redirectTo: PageRoute.Login,
      pathMatch: 'full'
  },
  {
      path: PageRoute.Login,
      component: LoginComponent,
      data: PageRouteData[PageRoute.Login]
  },
  {
      path: PageRoute.SignUp,
      component: SignupComponent,
      data: PageRouteData[PageRoute.SignUp]
  }
];

Side note: pathMatch is only necessary if you have a redirectTo

This way you do not need to import the app.routes in your PagesService and the circular dependency is resolved

like image 182
Poul Kruijt Avatar answered Sep 24 '22 03:09

Poul Kruijt