Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Injection error: Cannot resolve all parameters

Tags:

angular

I'm getting this error when trying to inject the Http service into my PanelsService.

import {Component} from 'angular2/core';
import {Http} from 'angular2/http';

export class PanelsService {

  constructor(public http:Http) { }

  getPanelFilters() {
    var url = '../../data/panelFilters/' + 13677 + '.json'

    return this.http.get(url)
  }

}

I'm attempting to access the PanelsService from my SidebarComponent:

import {PanelsService} from '../panels/panels.service';

@Component({
  ....
  providers: [PanelsService]
})

export class SidebarComponent implements OnInit {

  constructor(public panelsService:PanelsService) { }

  ngOnInit() {
    console.log('I am the sidebar component');
  }

}

It should be noted that my tsconfig.json also has the lines:

"emitDecoratorMetadata": true,
"experimentalDecorators": true,

I've tried using @Injectable as demonstrated here but when I decorate my class with @Injectable() I get an error in the console:

enter image description here

boot.js simply bootstraps my app component, it doesn't inject any dependencies:

import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from './components/app.component';

bootstrap(AppComponent).catch(err => console.error(err));

Any help would be appreciated.

like image 679
garethdn Avatar asked Dec 17 '15 14:12

garethdn


1 Answers

There's one thing missing in your code: Providers.

With

export class PanelsService {

  constructor(public http:Http) { }
}

You ask for a dependency that the injector identifies with the token Http (the type annotation). However, there's nothing in your code (at least as shown here), that tells your injector what it has to return for the token Http. So it's just half of the information.

In order to resolve a dependency we need a token (the thing we're asking for) and a provider (the thing that creates that object we're asking for). Provider can be configured either during bootstrap() or at component level using the providers property in the @Component() decorator.

Unless you want to create a new instance of Http every time, it makes most sense to configure that provider at bootstrap() to make the same instance available throughout your entire application.

Here's what a provider for Http could look like:

import {provide} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {Http} from 'angular2/http';

bootstrap(YourApp, [
  provide(Http, {useClass: Http})
]);

provide() takes a token Http and configures a provider with a recipe that describes how to create an object of something (useClass: Http). If the recipe is useClass and the class is the same as the token, we can use the following shorthand syntax:

bootstrap(YourApp, [
  Http
]);

However, we'll realise that this is not enough, since it turns out that Http uses DI itself for its own dependencies too. Which means, we need providers for those dependencies as well. Luckily, for these cases Angular already provides a predefined list of providers.

HTTP_PROVIDERS is a collection of provider configurations that are needed to make Http work. So all you have to do is:

import {HTTP_PROVIDERS} from 'angular2/http';

bootstrap(YourApp, [HTTP_PROVIDERS]);

Now your app knows about all dependencies, tokens and providers for anything Http.

You can find a more detailed explanation in this article.

like image 52
Pascal Precht Avatar answered Nov 12 '22 08:11

Pascal Precht