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

I have implemented an interceptor to add authorization header that i can make seucred api. I get an error when i inject this service in any app module // "Cannot instantiate cyclic dependency! HttpClient ("[ERROR ->]"): in NgModule AppModule in ./AppModule@-1:-1"

// auth interceptor to add authorization bearer

import { Injectable } from '@angular/core';
import {
  HttpRequest,
  HttpHandler,
  HttpEvent,
  HttpInterceptor
} from '@angular/common/http';
import { Auth } from './auth.service';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(public auth: Auth) {}
  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      setHeaders: {
        Authorization: `Bearer ${this.auth.getToken()}`
      }
    });
    return next.handle(request);
  }
}


// Auth service

    import { Injectable } from '@angular/core';
    import { Router } from '@angular/router';
    import { Observable } from 'rxjs/Observable';
    import 'rxjs/add/operator/map';
    import { HttpClient, HttpParams, HttpHeaders } from '@angular/common/http';

    @Injectable()
    export class Auth {
      // Store profile object in auth class
      userProfile: Object;
      public token: string;
      constructor(private router: Router, private http: HttpClient) {
          // set token if saved in local storage
          const currentUser = JSON.parse(localStorage.getItem('currentUser'));
          this.token = currentUser;
      }
      login(username: string, password: string) {
        const headers = new HttpHeaders()
          .set('Content-Type', 'application/x-www-form-urlencoded')
          .set('Accept', 'application/json');
        const params = new HttpParams().set('username', username).set('password', password)
          .set('grant_type', 'password');
        return this.http.post('http://rrrrr/token', params.toString(),
          { headers }).subscribe(data => {
            this.token = data['access_token'];
          console.log(this.token);
        },
        err => {
          console.log('Error occured');
        });
      }
      getToken() {
        return this.token;
      }
      logout(): void {
          // clear token remove user from local storage to log user out
          this.token = null;
          localStorage.removeItem('currentUser');
      }
      public authenticated(): boolean {
        // Check whether the current time is past the
        // access token's expiry time
        const expiresAt = JSON.parse(localStorage.getItem('expires_at'));
        return new Date().getTime() < expiresAt;
      }
    }


Solution 1:[1]

Your Auth service has a dependency on HttpClient, which is causing a circular dependency.

What you could do is break your Auth service into two: an Auth with most of your existing functionality, and an AuthContextService which has your getToken() function (and perhaps others). Your Auth service can then depend on your AuthContextService, and so can your AuthInterceptor.

Edit: Add some code to try and explain

@Injectable()
export class AuthContextService {
    // With getToken() in here, and not in Auth, you can use it in AuthInterceptor
    getToken(): string {
        return 'however you get your token';
    }   
}

@Injectable()
export class Auth {
    constructor (private http: HttpClient, private authContext: AuthContextService) {}

    authenticate(username: string, password: string) {
        // Do stuff
    }

    // Whatever other functions you already have on Auth.
}

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(public authContext: AuthContextService) {}

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    request = request.clone({
      setHeaders: {
        Authorization: `Bearer ${this.authContext.getToken()}`
      }
    });
    return next.handle(request);
  }
}

Solution 2:[2]

It's a known issue with several possible workarounds. It normally occurs in your auth interceptor service.

Changing the way you inject AuthService worked for me, see the code snippet below. Please note the usage of Injector here and the way you inject you AuthService directly in intercept() function.

import { Injectable, Injector } from '@angular/core';
import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
  HTTP_INTERCEPTORS,
} from '@angular/common/http';
import { Observable } from 'rxjs/Observable';
import { AuthService } from 'app/services/auth/auth.service';

@Injectable()
export class AuthInterceptor implements HttpInterceptor {
  constructor(private injector: Injector) {}

  intercept(
    req: HttpRequest<any>,
    next: HttpHandler,
  ): Observable<HttpEvent<any>> {
    // inject your AuthService here using Injector
    const auth = this.injector.get(AuthService);
    const authHeader = `Bearer ${auth.getToken()}`;
    const authReq = req.clone({
      headers: req.headers.set('Authorization', authHeader),
    });
    return next.handle(authReq);
  }
}

export const AuthHttpInterceptor = {
  provide: HTTP_INTERCEPTORS,
  useClass: AuthInterceptor,
  multi: true,
};

Solution 3:[3]

One common cause of this cyclic dependency! HttpClient ERROR is usually associated with a NullInjectorError.

So if you have an accompanying logged error about No provider for HttpClient! I believe this solution would help:

  1. Open app.module.ts file of Angular Application.
  2. Import HttpClientModule from @angular/common/http.
  3. Add HttpClientModule to the @NgModule imports array.

Your AppModule should look like this

import { HttpClientModule } from '@angular/common/http';

@NgModule({
imports: [
BrowserModule,
HttpClientModule,
],
declarations: [ AppComponent ],
bootstrap: [ AppComponent ]
})
export class AppModule { }

HttpClient is Angular's mechanism for communicating with a remote server over HTTP. You can check this link for more https://www.thecodebuzz.com/angular-null-injector-error-no-provider-for-httpclient/

Solution 4:[4]

Just add HttpClientModule to the providers section on app.module.ts

providers: [ HttpClientModule ]

Then you be able to inject HttpClient on any service or component.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2
Solution 3 Marcel
Solution 4 shop350