32

I am new to Ionic 2. I read in angular 2 docs, that service needs to be injected while bootstrap application. But could not see any bootstrap thing while going through Ionic 2 tutorial.

Any help is highly appreciated.

sebaferreras
  • 44,206
  • 11
  • 116
  • 134
VISHAL DAGA
  • 4,132
  • 10
  • 47
  • 53

3 Answers3

36

There is no use of Bootstrap() in Ionic2, only use of @App to declare your app. You still need to declare your service in your @Page component.

Create your service

import {Injectable} from "angular2/core";
import {Http} from "angular2/http";

@Injectable()
export class DataService {
  constructor(http: Http) {
    this.http = http;
    this.data = null;
  }

  retrieveData() {
    this.http.get('./mocks/test.json')
    .subscribe(data => {
      this.data = data;
    });
  }

  getData() {
    return this.data;
  }
}

Then use it in your @Page

import {Page} from 'ionic/ionic';
import {DataService} from './service';

@Page({
  templateUrl: 'build/test.html',
  providers: [DataService]
})
export class TestPage {
  constructor(data: DataService) {
    data.retrieveData()
  }
}
Raphael
  • 1,708
  • 13
  • 11
  • 8
    You can achieve similar functionality as bootstrap by adding the service to your `@App` providers array and **not** adding the service to providers of the said `@Page`. – Boštjan Pišler Jan 25 '16 at 17:08
  • 1
    Yes but it's a better practice to specify services where your are using them. – Raphael Jan 26 '16 at 07:24
  • A service has to be one singleton for whole app to share common data like cache, which means it has to be defined in top level component. If we are talking about model like services that is. Others, like http, on the other hand don't need to know about each other. – Boštjan Pišler Feb 01 '16 at 12:17
  • After following these steps, any clue about how to access the "data" variable used within `@Page` once the request finishes? – Adrián Navarro Feb 15 '16 at 18:01
  • Friends, please add this at the top import 'rxjs/Rx'; of the service in order to use the observables. :) (Otherwise you might get an error in the this.http.get() line) – Raja Yogan Feb 24 '16 at 20:20
  • I am not sure, but you may need the ``static get parameters(){ return [[Http]]; }`` below your line which says ``export class DataService`` – John Apr 20 '16 at 21:35
  • 4
    It's not a better practice to inject the service wherever needed, this creates a separate instance, which is usually not the desired behaviour of a service. Generally speaking, you will want a single instance which you will only inject in the @App. In your example, two different pages would have their own associated instances, so calling retrieveData() in page1, and trying to getData() in page2 would not return the data just retrieved. – Manu Valdés May 13 '16 at 05:58
  • I have one issue that when i am using getData() in any other folder then this is creating issue, because response from api is taking time then how i can use this ? – Anuj Apr 21 '17 at 10:19
  • I created a service similar to suggested but its giving me error: "Property 'http' does not exist on type 'DeviceConfService'". Anyone has any idea how to solve this? – Karthik Nagaraj Jun 20 '17 at 16:38
  • @AnKarthik I think you are trying to do `this.http` and `http` is not set to your Service class. To do that, you can write in the constructor `this.http = http;` or `constructor(private http: Http)` – Raphael Jun 21 '17 at 17:41
24

RC Update:

As of Ionic2 RC, now the services should be included in the providers array from the @NgModule to make those services work as singletons (meaning that the same instance will be used in the entire application).

@NgModule({
  declarations: [
    MyApp,

    // Pages
    Page1,
    Page2,

    // Pipes
    MyCustomPipe,

    // Directives
    MyCustomDirective,
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,

    // Pages
    Page1,
    Page2
  ],
  providers: [ DataService, NavigationService, Storage, ... ] // <- here!
})
export class AppModule {}

Old answer (2.0.0-beta.8)

Just in case if this could help other Ionic2 developers, with the release of 2.0.0-beta.8, now we can use ionicBootstrap to make our services work as singletons meaning that the same instance will be used in the entire application.

The changes needed to do this are minimum; your services will remain the same

/* Notice that the imports have slightly changed*/
import {Injectable} from "@angular/core";
import {Http} from "@angular/http";
import 'rxjs/Rx';

@Injectable()
export class DataService {
  constructor(http: Http) {
    this.http = http;
    this.data = null;
  }

  retrieveData() {
    this.http.get('./mocks/test.json')
    .subscribe(data => {
      this.data = data;
    });
  }

  getData() {
    return this.data;
  }
}

But instead of injecting it as a provider in your Component (which will cause a new instance of the service to be created everytime the component is loaded)

import {Component} from '@angular/core';
import {DataService} from './service';

@Component({
  templateUrl: 'build/test.html'
  /* This should not be done anymore */
  /* providers: [DataService] */
})
export class TestPage {
  constructor(data: DataService) {
    data.retrieveData()
  }
}

Just include it in the ionicBootstrap of your app.ts file, in order to ensure that the same instance of the service will be used in the entire application.

ionicBootstrap(MyApp, [DataService], {});

Angular Style Guide:

Following Angular2 Style Guide

Do provide services to the Angular 2 injector at the top-most component where they will be shared.

Why? The Angular 2 injector is hierarchical.

Why? When providing the service to a top level component, that instance is shared and available to all child components of that top level component.

Why? This is ideal when a service is sharing methods or state.

And

It will work. It's just not a best practice. The bootstrap provider option is intended for configuring and overriding Angular's own preregistered services, such as its routing support.

So Instead of registering the service in the ionicBootstrap, we'd have to register it in the top-most component of our App (if we want to use the same instance in the entire application), like this:

@Component({
  templateUrl: 'build/app.html',
  directives: [...],
  providers: [..., DataService]
})
class MyApp{ 
  // ...
} 
sebaferreras
  • 44,206
  • 11
  • 116
  • 134
  • 1
    This fixed it for me, thanks so much. Wondering where the documentation is on this, was hard to find with a vague error about Promises – webdevinci Jul 13 '16 at 21:50
  • Well, Ionic Team is still working on the documentation, but as Ionic2 is built on top of Angular2, you can find these kind of things in [Angular Style Guides](https://angular.io/docs/ts/latest/guide/style-guide.html) and other Angular Doc related pages. In order to know how the Injector works (which allowed me to understand this subject and write this answer), you can take a look at [this page](https://angular.io/docs/ts/latest/guide/hierarchical-dependency-injection.html). – sebaferreras Jul 14 '16 at 07:02
  • Hi. I tried following this example by @sebaferreras. It seems like the service is picked up, however, the screen generated is blank whenever I include the service. Any idea why that would be? The service resides in src/providers/global-alerts.ts – Cornelius Parkin Feb 08 '17 at 06:00
0

Search for Ionic Provider, in ionic instead of angular services we use ionic Provider, they provide the concept of Dependency Injection in Ionic.

generate the ionic provider

ionic generate provider <provider name>

and then import the provider in the root page or the page in which it needs to be used

and put in provider array

Kuldeep Kumar
  • 754
  • 1
  • 7
  • 12