Shailesh Ladumor
Shailesh Ladumor

Reputation: 7242

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

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.

Upvotes: 15

Views: 11274

Answers (3)

Random
Random

Reputation: 3236

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();
}

Upvotes: 0

Bart Verkoeijen
Bart Verkoeijen

Reputation: 17753

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(['/']);
  }
}

Upvotes: 25

Shailesh Ladumor
Shailesh Ladumor

Reputation: 7242

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)
        );
}

Upvotes: 7

Related Questions