Search code examples
angulartypescriptangular2-services

Can't resolve all parameters for AuthenticationService: ([object Object], ?, [object Object])


I faced with next error and cannot understand how to resolve it.

Can't resolve all parameters for AuthenticationService: ([object Object], ?, [object Object])

I've checked almost every topic here and have tried multiple ways to resolve it but still can't beat it already second day.

I have tried to inject first authService in appService like this but getting same error

@Inject(forwardRef(() => AuthenticationService)) public authService: AuthenticationService

I have checked all DI and order of imports inside services and it seems to me everything is correct

So I appreciate if somebody could help me deal with it.

Angular 4.0.0

AuthService

    import { Injectable } from '@angular/core';
import {Http, Headers, Response} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {Observable} from 'rxjs/Rx';

import {AppServices} from "../../app.services";
import {Router} from "@angular/router";

@Injectable()
export class AuthenticationService {
  public token: any;

  constructor(
    private http: Http,
    private appService: AppServices,
    private router: Router
  ) {
    this.token = localStorage.getItem('token');
  }

  login(username: string, password: string): Observable<boolean> {
    let headers = new Headers();
    let body = null;
    headers.append("Authorization",("Basic " + btoa(username + ':' + password)));

    return this.http.post(this.appService.api + '/login', body, {headers: headers})
      .map((response: Response) => {
        let token = response.json() && response.json().token;
        if (token) {
          this.token = token;
          localStorage.setItem('Conform_token', token);
          return true;
        } else {
          return false;
        }
      });
  }

  logout(): void {
    this.token = null;
    localStorage.removeItem('Conform_token');
    this.router.navigate(['/login']);
  }
}

App Services

import {Injectable} from '@angular/core';
import {Headers, Http, RequestOptions} from '@angular/http';
import {Router} from "@angular/router";
import {AuthenticationService} from "./auth/auth.service";

import 'rxjs/add/operator/toPromise';
import {Observable} from 'rxjs/Rx';

@Injectable()

export class AppServices {

  api = '//endpoint/';

  public options: any;
  constructor(
    private http: Http,
    private router: Router,
    public authService: AuthenticationService // doesn't work
  //  @Inject(forwardRef(() => AuthenticationService)) public authService: AuthenticationService // doesn't work either
      ) {
        let head = new Headers({
      'Authorization': 'Bearer ' + this.authService.token,
      "Content-Type": "application/json; charset=utf8"
    });
    this.options = new RequestOptions({headers: head});
  }

  // ====================
  //    data services
  // ====================

  getData(): Promise<any> {
    return this.http
      .get(this.api + "/data", this.options)
      .toPromise()
      .then(response => response.json() as Array<Object>)
      .catch((err)=>{this.handleError(err);})
  }

App Module

import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import {BaseRequestOptions, HttpModule} from '@angular/http';

import { MaterialModule} from '@angular/material';
import {FlexLayoutModule} from "@angular/flex-layout";
import 'hammerjs';

import { routing, appRoutingProviders }  from './app.routing';
import { AppServices } from './app.services';
import {AuthGuard} from "./auth/auth.guard";
import {AuthenticationService} from "./auth/auth.service";

import {AppComponent} from './app.component';
import {AuthComponent} from './auth/auth.component';
import {NotFoundComponent} from './404/not-found.component';
import { HomeComponent } from './home/home.component';

@NgModule({
  declarations: [
    AppComponent,
    AuthComponent,
    NotFoundComponent,
    HomeComponent
  ],
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    FormsModule,
    HttpModule,
    routing,
    MaterialModule,
    FlexLayoutModule
  ],
  providers: [AppServices, AuthGuard, AuthenticationService],
  bootstrap: [AppComponent]
})
export class AppModule { }

Solution

  • You have a circular dependency between AppServices and AuthenticationService - that's not possible with constructor injection like Angular uses.

    To work around you can use

    export class AuthenticationService {
      public token: any;
      appService: AppServices;
      constructor(
        private http: Http,
        // private appService: AppServices,
        injector:Injector;
        private router: Router
      ) {
        setTimeout(() => this.appService = injector.get(AppServices));
        this.token = localStorage.getItem('token');
      }
    

    See also DI with cyclic dependency with custom HTTP and ConfigService

    To avoid setTimeout you can also set AuthenticationService.appService from the constructor of AppService (or the other way around)