I am attempting to inject Http from Angular2/Http into a Page element, and am not seeing a direct way to do this.
I browsed through the source for the Page element and noticed it does not accept a providers array like it would for @Component or @App. It also appears that the bootstrap is being done well away from the @App component where I would expect it, which is limiting my ability to inject as well.
and attepted to call in in my GettingStarted page via: export class GettingStartedPage { constructor(nav: NavController, @Inject(Http)http: Http) {
This yields the following error:
EXCEPTION: Cannot resolve all parameters for GettingStartedPage(NavController, @Inject(undefined)). Make sure they all have valid type or annotations.
Considering that the @App annotation signifies the root component of the application, the Http service should have been availible in the component. I have confirmed that the injection on the application annotation does provide injection in the application class.
I also attempted to utilize both an @Page and @Component, but this breaks some of the ionic component selectors for some reason.
Is there another way in which I should be able to inject the Http provider into a component with an @Page annotation, or a more appropriate way to handle this?
Also, you might want to keep the controllers lean and use http calls and such in Services rather than the page controller directly:
import {Injectable} from 'angular2/angular2';
import {Http, Headers} from 'angular2/http';
@Injectable()
export class DBClientService {
constructor(http: Http) {
this.http = http;
}
read(id){
this.http.get(...
For a Page, this not any different – things can be injected like this (optimally you’d inject that DBClientService to the Page controller). But here’s how to inject http to the controller:
import {IonicApp, Page, NavController} from 'ionic/ionic';
import {Http, Headers} from 'angular2/http';
@Page({
templateUrl: 'app/test/test.html',
})
export class TestPage{
constructor(app: IonicApp, nav: NavController, http: Http) {
this.nav = nav;
this.app = app;
this.http = http;
// Optionally, set headers like this
this.headers = new Headers();
this.headers.append('Content-type', 'text/plain');
}
The overall intention was for this to be a service, but I was attempting to work backwards as I was having problems with the http injection. I tested the suggestion for the Page, which seems to work (I’m rather surprised I didn’t try that earlier), but the service is still failing as suggested above. For the sake of being thorough, here is the import and constructor block of my service:
import {Injector, Injectable} from 'angular2/angular2'
import {Http, HTTP_PROVIDERS, URLSearchParams, Headers} from 'angular2/http'
import {OauthBase} from "./OauthBase";
import IOauthObject from "./IOauthObject";
import Observable from "../../../../node_modules/@reactivex/rxjs/src/Observable";
import ErrorObservable from "../../../../node_modules/@reactivex/rxjs/src/observables/ErrorObservable";
import * as config from '../../config'
import * as jsSHA from "../../../../bower_components/jsSHA"
export {Twitter}
@Injectable()
class Twitter extends OauthBase {
//region Private Variables
private static _http:Http;
private static _redirect_uri: string;
private _oauthObject: IOauthObject;
private _options: {};
//endregion
//region Singleton Generators
private static _instance = new Twitter();
constructor(http: Http) {
Twitter._http = http;
if (Twitter._instance) {
throw new Error("Error: Instantiation failed. Use GetInstance() instead.")
}
Twitter._instance = this;
Twitter._redirect_uri = "http://localhost/callback";
super();
}
With this implementation the http property is undefined within the constructor. If I add the following to the constructor, it is defined, but it feels sloppy. Do you have any suggestions about what might be going wrong?
var injector = Injector.resolveAndCreate([
HTTP_PROVIDERS]);
Twitter._http = injector.get(Http);
I tested with Ionic alpha 37, using the following code:
app.js
import {App, IonicApp, Platform} from 'ionic/ionic';
import './app.scss';
import {Twitter} from './twitter/twitter';
// Do add your own services here as providers, but not Http
@App({
templateUrl: 'app/app.html',
providers: [Twitter]
})
class MyApp {
constructor(app: IonicApp, platform: Platform, twitter: Twitter) {
this.app = app;
this.platform = platform;
this.twitter = twitter;
}
}
twitter/twitter.js
import {Injectable} from 'angular2/angular2'
import {Http} from 'angular2/http'
@Injectable()
export class Twitter {
constructor(http: Http) {
this._http = http;
console.log('all OK', this._http);
}
}
And this works OK!
Maybe if you test this minimal code first, and start adding things to the service one by one to see what breaks it?
Sidenote:
The singleton generator; is it really needed? If you mark the Twitter class as a provider in the app.js under @App, Angular should take care of instantiating the single instance - then just injecting it in all places as needed. Or maybe I am missing something / some things you need for other code using the class?