Oam Psy
Oam Psy

Reputation: 8663

Angular Local Lib StaticInjectorError(AppModule)[HttpHandler -> Injector]

I have had a working app for a few months now with no issues. I am trying to move some common services out into a library that can be used by other apps.

I am trying to do this without the Angular CLI (just for learning purposing). I am using angular 7.1.1

Project structure:

- site
    .gitlab-ci.yml
    - core-lib
        package.json
        tsconfig.json
        - src
            index.ts
            core
                my.service.js

    - ui-site
        package.json
        tsconfig.json
        - app
            app.modules.ts
            - table
                table.component.ts
                table.module.ts

core-lib > package.json

{
  "name": "core-lib",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "core-js": "^2.5.7",
    "lodash": "^4.17.11",
    "moment": "^2.22.2",
    "rxjs": "6.3.3",
    "zone.js": "0.8.11"
  },
  "devDependencies": {
    "@angular/common": "7.1.1",
    "@angular/compiler": "7.1.1",
    "@angular/core": "7.1.1",
    "@angular/forms": "7.1.1",
    "@angular/platform-browser": "7.1.1",
    "@angular/platform-browser-dynamic": "7.1.1",
    "@angular/router": "7.1.1",
    "@types/core-js": "0.9.35",
    "@types/jasmine": "7.2.48",
    "@types/node": "7.0.5",
    "typescript": "3.3"
  }
  "peerDependencies": {
    "@angular/common": "7.1.1",
    "@angular/compiler": "7.1.1",
    "@angular/core": "7.1.1",
    "@angular/forms": "7.1.1",
    "@angular/router": "7.1.1",
    "rxjs": "6.3.3",
    "zone.js": "0.8.11"
  }
}

core-lib > tsconfig.json

{
    "compilerOptions": {
        "target": "es6",
        "module": "es6",
        "lib": ["es6", "es2016", "dom"],
        "moduleResolution": "node",
        "sourceMap": true,
        "rootDir": "src",
        "baseUrl": "src",
        "sourceMap": true,
        "experimentalDecorators": true,
        "allowJs": true,
        "preserveSymlinks": true,
        "typeRoots": ["./node_modules/@types"],
        "paths": {
            "@angular/*": [
                "../node_modules/@angular/*"
            ]
        },            
    },
    "include": [
        "./src/**/*"
    ]
}

core-lib > src > index.ts

import { ModuleWithProviders, NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { HttpClientModule } from '@angular/common/http';
import { MyService } from './core/my.service';


@NgModule({
    imports: [CommonModule, HttpClientModule],
    exports: [HttpClientModule]
})

export class SharedModule {
  static forRoot(): ModuleWithProviders {
    return { 
        ngModule: SharedModule, 
        providers: [MyService]
    };
  }
}

MyService is very simple, it uses httpClient to get a local .json file as seen here: https://stackblitz.com/edit/angular-chcpcx

When i run tsc.cmd, i can see the compiler has successfully created the .js and .sourcmap files.

ui-site > package.json

{
  "name": "ui-site",
  "version": "1.0.0",
  "private": true,
  "dependencies": {
    "@angular/common": "7.1.1",
    "@angular/compiler": "7.1.1",
    "@angular/core": "7.1.1",
    "@angular/forms": "7.1.1",
    "@angular/platform-browser": "7.1.1",
    "@angular/platform-browser-dynamic": "7.1.1",
    "@angular/router": "7.1.1",
    "@types/core-js": "0.9.35",
    "@types/jasmine": "7.2.48",
    "@types/node": "7.0.5",
    "core-js": "^2.5.7",
    "lodash": "^4.17.11",
    "moment": "^2.22.2",
    "rxjs": "6.3.3",
    "zone.js": "0.8.11",
    "d3": "3.5.12",
    "jquery": "3.1.0",
    "core-lib": "file:../core-lib"
  },
  "devDependencies": {
    "@types/core-js": "0.9.35",
    "@types/jasmine": "7.2.48",
    "@types/node": "7.0.5",
  }
}

When i run npm install with the above, there are no issues and i can see the core-lib directory and files within the ui-site > node_modules folder

ui-site > app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { RouterModule } from '@angular/router';
import { HttpClientModule } from '@angular/common/http';

import { TableModule } from './table/table.module';
import { SharedModule } from '../node_modules/core-lib/src/index';

@NgModule({
  imports:      [ BrowserModule, RouterModule, HttpClientModule, SharedModule.forRoot(), TableModule ],
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

ui-site > app > table > table.component

  import { Component } from '@angular/core';
  import { MyService } from '../../../node_modules/core-lib/src/core/my.service'

  @Component({
      template: `hi`
  })

  export class TableComponent {

      constructor(private myService: MyService) {
          this.myService..requestConfig()
              .subscribe((config) => {        
                  console.log(config);
              },
              (err) => {
                 console.log(err)
              });
      }

  }

Error in browser:

Error: StaticInjectorError(AppModule)[HttpHandler -> Injector]: 
   StaticInjectorError(Platform: core)[HttpHandler -> Injector]: 
      NullInjectorError: No provider for Injector!

Upvotes: 1

Views: 1218

Answers (1)

Suren Srapyan
Suren Srapyan

Reputation: 68665

Are you missing to call forRoot? In your example you have

SharedModule.forRoot

@NgModule({
  imports:      [ ..., SharedModule.forRoot, TableModule ],
  //                                       ^
  declarations: [ AppComponent ],
  bootstrap:    [ AppComponent ]
})

export class AppModule { }

After update

If you use Windows 10 and a service from a npm linked libraries, try to add

"preserveSymlinks": true

into

angular.json at projects/*/architect/build/options

Upvotes: 1

Related Questions