Angular 2 Dependency Injection: Can't resolve all parameters (no dep chain, no barrel)

1.7k Views Asked by At

I've been trying to follow one example in the ng-book 2 and ran into difficulties in the DI chapter.

@Component({
    selector: 'app-root',
    template: `
        <button (click)="invokeService()">Get Value</button>
    `
})
export class AppComponent {
    constructor(public myService: MyService) {}

    invokeService() {
        console.log(this.myService.getValue());
    }
}
@Injectable()
export class MyService {
    getValue(): string {
        return 'a value';
    }
}
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [MyService],
  bootstrap: [AppComponent]
})
export class AppModule { }

here's a plunker https://plnkr.co/edit/KSXE9tnRj4tffiISyp0i it totally works when creating the ReflectiveInjector manually, but when i try to take the easy way and declare it in providers on the NgModule it fails giving me "Can't resolve all dependencies for AppComponent". I checked the other answers and as you see there are no circular deps or barrel-related problems - it's all in one file. Any hints would appreciated!

1

There are 1 best solutions below

1
On BEST ANSWER

If you are putting multiple classes in one file (I'm sure this is for testing only), the order of the files must be in check. Say your AppComponent is referencing your MyService, so the definition of MyService must be put on top of AppComponent. Hence, your code must look something like this:

import { Component, ReflectiveInjector, Injectable, Inject } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

@Injectable()
export class MyService {
    constructor() {}

    getValue(): string {
        return 'a value';
    }
}

@Component({
    selector: 'app-root',
    template: `
    <button (click)="invokeService()">Get Value</button>
    `
})
export class AppComponent {
    // private myService: MyService;

    constructor(public myService: MyService) {
        // let injector: any = ReflectiveInjector.resolveAndCreate([MyService]);
        // this.myService = injector.get(MyService);
        // console.log('Same instance? ', this.myService === injector.get(MyService));
    }

    invokeService() {
        console.log(this.myService.getValue());
    }
}

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [MyService],
  bootstrap: [AppComponent]
})
export class AppModule { }