Cannot instantiate cyclic dependency! ApplicationRef ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1
Asked Answered
S

3

15

I have added this code into my app.module.ts

    providers: [ AppConfigService,
            {
                provide: APP_INITIALIZER,
                useFactory: (config: AppConfigService) => () => config.getAppConfig(),
                deps: [AppConfigService],
                multi: true
            },
]

Getting this error

enter image description here

Issue: i have used ngx-permission pkg for permission. i set route permission method. but when i refresh a page that time redirect on home page instead stay on current page. so i tried to load permissions before application start up method for resolve this issue but got this error.

 config.getAppConfig() // call when application start up

have any idea please help. other solution also welcome.

Stellite answered 27/9, 2017 at 6:42 Comment(1)
How a service can be declared dependant on iself ? It seems to me that in "deps" you shall give Angular modules, not services. Can you just use a empty list as deps ?Wickham
S
7

i had fixed my issue with this solution

create function into app.module.ts

export function loadConfig(appService: AppConfigService): Function {
    return () => appService.getAppConfig();
}

 AppConfigService,
        {
            provide: APP_INITIALIZER,
            useFactory: loadConfig,
            deps: [AppConfigService],
            multi: true
        },

issue into `HttpInterceptor` so i used injector for that
constructor(private inj: Injector) {
        super(
            inj.get(XHRBackend),
            inj.get(RequestOptions)
        );
}
Stellite answered 15/3, 2018 at 11:50 Comment(1)
Where you use the constructor? IPitchblende
A
25

This error can happen when the dependencies in your APP_INITIALIZER have a dependency on an Angular service, e.g. Router.

The solution is lazy injection by changing the constructor of your service to accept a Injector instead, and then resolve the value outside the constructor.

Example AppConfigService:

import { Injectable, Injector } from '@angular/core';
import { Router } from '@angular/router';

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

  // Helper property to resolve the service dependency.
  private get _router() { return this._injector.get(Router); }

  constructor(
    //private _router: Router
    private _injector: Injector
  ) { }

  navigate() {
    this._router.navigate(['/']);
  }
}
Ander answered 16/10, 2019 at 10:24 Comment(1)
your answer actualy inspired me not to use APP_INITIALIZER but create own APP_START token which is used in some app core module constructor to load all services after angular modules are readyThornberry
S
7

i had fixed my issue with this solution

create function into app.module.ts

export function loadConfig(appService: AppConfigService): Function {
    return () => appService.getAppConfig();
}

 AppConfigService,
        {
            provide: APP_INITIALIZER,
            useFactory: loadConfig,
            deps: [AppConfigService],
            multi: true
        },

issue into `HttpInterceptor` so i used injector for that
constructor(private inj: Injector) {
        super(
            inj.get(XHRBackend),
            inj.get(RequestOptions)
        );
}
Stellite answered 15/3, 2018 at 11:50 Comment(1)
Where you use the constructor? IPitchblende
B
0

I had the same issue to dynamically update routes.
Actually, you don't have to inject dependencies manually. All you have to do is split the cycle. First resolve dependency, and then use them.
Here is an exemple for the router, but you can set any dependency you like.

// AppModule
{
  provide: APP_INITIALIZER,
  useFactory: myFactoryUpdatingRoutes, // init routes from special config
  multi: true,
  deps: [MyRouterLoader],
},

Config class:

@Injectable({
  providedIn: 'root',
})
export class MyRouterLoader{
  // MyRouterLoader prevents cyclic dependencies.
  // Router cannot be part of "deps" of AppModule's APP_INITIALIZER
  // so we have to split dependencies resolving
  constructor(private router: Router,
              private routeConfig: MySpecialRoutesConfig) { }

  // actually update routes
  public injectSpecialRoutes() {
    this.router.resetConfig([
      {
        path: this.routeConfig.urls['my-home-url-key'],
        component: HomeComponent
      },
      {
        path: this.routeConfig.urls['my-admin-url-key'],
        component: AdminComponent
      },
      {
        path: '**',
        redirectTo: '/',
      }
    ])
  }
}

export function myFactoryUpdatingRoutes(myRouterLoader: MyRouterLoader) {
  myRouterLoader.injectSpecialRoutes();
}
Banal answered 29/7, 2021 at 12:14 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.