2

I am trying to use angular 2 Http service but I am getting

Can't resolve all parameters for AppComponent: (?)

Which has this signature

 constructor(public http:Http){ }

I tracked the problem down to declaring the providers for Http.

In the angular 2 quickstart they say

In this demo, we register providers by importing other NgModules to our root NgModule.

But I already have

@NgModule({
    imports: [ BrowserModule, HttpModule, FormsModule ],
    declarations: [AppComponent],
    bootstrap: [AppComponent]
})

So, I understand the providers should be fine.

In the code documentation for file http.d.ts I find this:

 * import {Http, HTTP_PROVIDERS} from '@angular/http';

But when I try to write this, I get that HTTP_PROVIDERS does not exist (I guess it is before GA)

The only way I can solve this error is by adding @Inject(Http) in the signature.

How can I make it work without adding @Inject(Http) in the signature?

This is my systemjs config

  <script>
        System.config({
            transpiler: 'typescript',
            map: {
                '@angular/core': './node_modules/@angular/core/bundles/core.umd.js',
                '@angular/platform-browser-dynamic': './node_modules/@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
                '@angular/platform-browser': './node_modules/@angular/platform-browser/bundles/platform-browser.umd.js',
                '@angular/compiler': './node_modules/@angular/compiler/bundles/compiler.umd.js',
                '@angular/common': './node_modules/@angular/common/bundles/common.umd.js',
                '@angular/http': './node_modules/@angular/http/bundles/http.umd.js',
                '@angular/forms': './node_modules/@angular/forms/bundles/forms.umd.js',
                'rxjs': './node_modules/rxjs'
            },
            packages: {
                './app': {
                    defaultExtension: 'ts'
                },
                '@angular/http':{
                    defaultExtension:'ts'
                },
                'rxjs': {
                    defaultExtension: 'js'
                }
            }
        })

        System.import('./app/main.ts').catch(function (err) {
            console.error(err);
        });

    </script>

This is my tsconfig.json

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false
  }
}

You can see all my code at https://github.com/GuyMograbi/angular2-simple-setup

guy mograbi
  • 27,391
  • 16
  • 83
  • 122

3 Answers3

2

You need to add HttpModule to imports in NgModule

@NgModule({
  imports: [BrowserModule, HttpModule]
  ...
})

No need for @Inject() for Http.

Ensure you have properly imported (TS imports) everything Http, HttpModule, ...

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
2

Completely rewriting my answer to be better targeted.

Your module:

import {...} from '@angular/...';

import {HttpModule} from '@angular/http';

@NgModule({
    imports: [..., HttpModule],
    declarations: [...],
    exports: [...],
    providers: [...]
})
export class AppModule {}

Your component:

import {Component} from '@angular/core';
import {Http} from '@angular/http';

@Component({
    selector: 'my-app',
    template: `...`
})
export class AppComponent{

    constructor(private http: Http){
    }

    private getMyData(){
        return this.http.get(...)
            .map(...)
            .subscribe(...);
    }
}

That should be all you need. There is no @Injectable decorator on the AppComponent because it's a @Component, it's not an injectable service.

Angular takes care of injecting for you, so you shouldn't need to do any kind of @Inject(Http) anywhere.

Only your own services that you create that you want components (or other services) to use should be created as @Injectable. E.g.

import {Injectable} from '@angular/core';

@Injectable()
export class SomeService{
    doSomething(){
        //...
    }
}

You would add that SomeService to either your Module level providers array (for app-level singleton) or even your Component's own providers array (for new instances along with the components).

import {SomeService} from './some.service';

@Component({
    selector: '...',
    template: '...',
    providers: [SomeService]
})
export class SomeComponent{ 
    constructor(private someService: SomeService){
        // someService is a new instance of SomeService (not a singleton)
    }
}

Notice, though, that there's no additional @Inject code - the providers (either module level or component level, depending on your needs), deal with creating an instance for you, and passing it to the constructor.

Edit to respond to the updated question:

I think your systemjs.config might be wrong. I see your app pointing to a ts file instead of js. Browsers don't really run ts, ts needs compiling (transpiling - pick your term of choice) into js. The js is what systemjs.config should be loading, not the ts.

packages: {
    app: {
        main: './main.js',
        defaultExtension: 'js'
    },
    rxjs: {
        defaultExtension: 'js'
    },
    'angular-in-memory-web-api': {
        main: './index.js',
        defaultExtension: 'js'
    }
}
Krenom
  • 1,894
  • 1
  • 13
  • 20
  • I am trying to inject http directly to my appComponent which is annotated with `@Component` and I get an error. How can I resolve this? – guy mograbi Oct 07 '16 at 12:39
  • I updated the question to make it clean. I do not have DataService - it is a code snippet from the article demonstrating 2 ways of injecting http. One works, the other does not.. how can I make the other one (@Injectable) work as well? – guy mograbi Oct 07 '16 at 12:42
  • @guymograbi Which article are you following? Are using the release v2.0.x? Why exactly are you trying to inject the services yourself instead of leaving it to Angular to do it for you? Your question still shows you using an `@Injectable` decorator in the `AppComponent`. It is not injectable, it is a `@Component`. The Http is (under the hood) `@Injectable`, whereas your `AppComponent` is not. – Krenom Oct 07 '16 at 14:09
  • Thank you for clarifying that up! I did miss the fact that @injectable should be on the service and not the component. So according to your comment, all I need is to use is `@Component` - but when I do this, I get `(SystemJS) Can't resolve all parameters for AppComponent: (?)` - which lead me to the article I link in my question. – guy mograbi Oct 08 '16 at 13:59
  • so my question might be like: http://stackoverflow.com/a/35371225/1068746 – guy mograbi Oct 08 '16 at 14:02
  • but I still can't make it to work properly. I would like to make it work without `@Inject`. update the question to focus on the correct problem. thanks! – guy mograbi Oct 08 '16 at 14:12
  • @guymograbi Seems as though it's your TS compiling issue like you linked.. Updating my answer to include a snippet from my own systemjs.config - yours I think might be wrong. – Krenom Oct 08 '16 at 17:34
  • nope - that is actually the correct configuration. I think it is something about providers.. can't put my finger on it.. I think the providers should be registered once I add `HttpModule` to `imports`. – guy mograbi Oct 08 '16 at 17:47
  • I rephrased the question completely thanks to your comments. – guy mograbi Oct 09 '16 at 17:15
2

You should add typescriptOptions to your systemjs configuration

index.html

 System.config({
    transpiler: 'typescript',
    typescriptOptions: {
     "emitDecoratorMetadata": true
    },
    map: {
    ....

See also angularjs 2.0: Can't inject anything through component constructor()

Your tsconfig.json isn't used in your configuration. You're transpiling files on the fly. You could take a look at this simple seed project https://github.com/alexzuza/angular2-typescript-systemjs

Community
  • 1
  • 1
yurzui
  • 205,937
  • 32
  • 433
  • 399