Boris Callens
Boris Callens

Reputation: 93337

Injecting ActivatedRoute gives cyclic dependency error

I'm trying to use ActivatedRoute in an app-root scoped service but getting a Cyclic dependency error I don't understand and don't know how to troubleshoot.

In my application I have a service to get the Community from a top level route parameter.
This service is used throughout my application in multiple components and other services.
When I inject ActivatedRoute in my constructor I get

Error: Provider parse errors:
Cannot instantiate cyclic dependency! Router ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1

When I inject the Injector iteslf instead and then get the ActivatedRoute in the constructor I get a recursion error. When I get the ActivatedRoute a little later in a method it does work as expected.

@Injectable()
export class CommunityService {

    constructor(
        private injector: Injector
        // private router: ActivatedRoute => Cyclic dependency
    ) {
        // const router = this.injector.get(ActivatedRoute); => InternalError: "too much recursion"
    }

    public getCommunity(): Community {
        const router = this.injector.get(ActivatedRoute); // this should not be needed
        const communityCode = router.snapshot.paramMap.get('community');
        return getCommunityByCode(communityCode);
    }
}

There are similar questions already but they are about HttpInterceptors. This is a regular service.

While creating a Stackblitz for @Alex I realized we provided the community service at APP_INITIALIZER time. This was the missing piece.

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent }  from './app.component';
import { ContentService } from '@common/services/content.service';

export function loadContent(content: ContentService) {
    return () => content.load();
}

@NgModule({
  imports:      [ BrowserModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ],
  providers: [ { provide: APP_INITIALIZER, useFactory: loadContent, deps: [ContentService], multi: true }],
})
export class AppModule { }

Upvotes: 2

Views: 869

Answers (2)

Boris Callens
Boris Callens

Reputation: 93337

When providing a service at APP_INITIALIZER time, not all angular services are initialized yet. The ContentService constructor, however, expected an initialized ActivatedRoute to be injected. This somehow resulted in cyclic dependency.

providers: [ { provide: APP_INITIALIZER, useFactory: loadContent, deps: [ContentService], multi: true }],

When the service is provided like other services, this is no longer the case.

providers: [ ContentService ]

Upvotes: 1

Sev
Sev

Reputation: 77

Try removing private injector: Injector and keep private router: ActivatedRoute and call the router variable wherever you want using this.router. If that's still not working I'm going to need the code in stackblitz or somewhere else so I can look deeper at your code

Upvotes: 1

Related Questions