Search code examples
angularangular12

No provider for HttpHeaders in Angluar 12


I am getting this error below when I try to use the get and post methods in a component. I tried to extend but it seems that that is no longer possible as HttpClient is final. Even then, I got the same error.

  ERROR Error: Uncaught (in promise): NullInjectorError: R3InjectorError(LayerListModule)[LayerListService -> EsriHttp -> EsriHttp -> HttpHeaders -> HttpHeaders -> HttpHeaders]: 
    NullInjectorError: No provider for HttpHeaders!
  NullInjectorError: R3InjectorError(LayerListModule)[LayerListService -> EsriHttp -> EsriHttp -> HttpHeaders -> HttpHeaders -> HttpHeaders]: 
    NullInjectorError: No provider for HttpHeaders!
      at NullInjector.get (core.js:11101)
      at R3Injector.get (core.js:11268)
      at R3Injector.get (core.js:11268)
      at R3Injector.get (core.js:11268)
      at injectInjectorOnly (core.js:4751)
      at ɵɵinject (core.js:4755)
      at injectArgs (core.js:4832)
      at Object.factory (core.js:11522)
      at R3Injector.hydrate (core.js:11438)
      at R3Injector.get (core.js:11257)
      at resolvePromise (zone.js:1213)
      at resolvePromise (zone.js:1167)
      at zone.js:1279
      at ZoneDelegate.invokeTask (zone.js:406)
      at Object.onInvokeTask (core.js:28660)
      at ZoneDelegate.invokeTask (zone.js:405)
      at Zone.runTask (zone.js:178)
      at drainMicroTaskQueue (zone.js:582)
      at ZoneTask.invokeTask [as invoke] (zone.js:491)
      at invokeTask (zone.js:1600)
  defaultErrorLogger @ core.js:6479
  handleError @ core.js:6527
  next @ core.js:29284
  __tryOrUnsub @ Subscriber.js:183
  next @ Subscriber.js:122
  _next @ Subscriber.js:72
  next @ Subscriber.js:49
  next @ Subject.js:39
  emit @ core.js:25936
  (anonymous) @ core.js:28699
  invoke @ zone.js:372
  run @ zone.js:134
  runOutsideAngular @ core.js:28572
  onHandleError @ core.js:28699
  handleError @ zone.js:376
  runGuarded @ zone.js:147
  api.microtaskDrainDone @ zone.js:1074
  drainMicroTaskQueue @ zone.js:589
  invokeTask @ zone.js:491
  invokeTask @ zone.js:1600
  globalZoneAwareCallback @ zone.js:1626

Is there anything I am missing in the code below?

  import { Injectable } from '@angular/core';
  import { HttpClient } from '@angular/common/http';
  import { Observable } from 'rxjs';
  
  @Injectable()
  export class EsriHttp {
    private _http: HttpClient;
    get(url: string, options?: {headers?: {[header: string]: string | string[]} }): Observable<any> {
      options = this.setOptions(options);
      return this._http.get(url, options);
    }
  
    post(url: string, body: any, options?: {headers?: {[header: string]: string | string[]} }): Observable<any> {
      options = this.setOptions(options);
      body = this.transformRequest(body);
      return this._http.post(url, body, options);
    }
  
    private setOptions(options?: {headers?: {[header: string]: string | string[]}}) {
      if (options == null) {
        options = {headers: null };
  
      }
      if (options.headers === null) {
          options.headers = {'Content-Type': 'application/x-www-form-urlencoded'};
      }
  
      return options;
    }
  
    private transformRequest(body) {
      if (!body.hasOwnProperty("f")) {
        body.f = "json";
      }
      let transform = (obj: any) => {
        let str = [];
        Object.keys(obj).forEach(function (key) {
          str.push(encodeURIComponent(key) + "=" + encodeURIComponent(obj[key]));
        });
        return str.join("&");
      };
      return transform(body);
    }
  }

Solution

  • I got the answer in this post even though the usage is slightly different.

    My app.module.ts

    import {Injector} from '@angular/core';
    
    export let InjectorInstance: Injector; // Move it to top otherwise, @NgModule will throw an error
    
    export class AppModule {
       constructor(private injector: Injector) {
       InjectorInstance = this.injector;
     }
    }
    

    My service file.

    import { Injectable } from '@angular/core';
    import { HttpClient } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import {InjectorInstance} from '../app.module';
    
    @Injectable()
    export class EsriHttp{
       private _http: HttpClient;
      constructor(){
         this._http = InjectorInstance.get<HttpClient>(HttpClient);
      }
    
      get(url: string, options?: {headers?: {[header: string]: string | string[]} }): Observable<any> {
        options = this.setOptions(options);
        return this._http.get(url, options);
      }
      // The same for post method