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!
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.
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.
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With