What is the proper way to create a shared provider in Ionic 2

I am trying to share a services data and functions amongst all of my components in my application. So far I have added to the @NgModule providers section and tried to use it in my components by importing the service and adding a private: MyService to the constructor.

So far none of this is working. My data keeps coming back undefined despite it being set in another component. Thanks in advance!

I really have no clue what is going on.

My app.component.ts file looks like below

import { NgModule } from '@angular/core';
import { IonicApp, IonicModule } from 'ionic-angular';
import { MyApp } from './app.component';
import { PastVideosPage } from '../pages/past-videos/past-videos';
import { HomePage } from '../pages/home/home';
import { TabsPage } from '../pages/tabs/tabs';
import { SignInPage } from "../pages/sign-in/sign-in";
import { SideMenu } from "../pages/side-menu/side-menu";
import { SharePromoVidModal } from "../page-modals/share-promo-vid/share-promo-vid";
import { AuthorizationService } from "../providers/authorization-service";

@NgModule({
  declarations: [
    MyApp,
    PastVideosPage,
    HomePage,
    TabsPage,
    SignInPage,
    SideMenu,
    SharePromoVidModal
  ],
  imports: [
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    PastVideosPage,
    HomePage,
    TabsPage,
    SignInPage,
    SideMenu,
    SharePromoVidModal
  ],
  providers: [AuthorizationService]
})
export class AppModule {}

And a component where i’m trying to use it looks like this

import { Component } from '@angular/core';
import { NavController, ModalController } from 'ionic-angular';
import { VimeoService, VimeoVideoConfig } from "../../providers/vimeo-service";
import { SharePromoVidModal } from "../../page-modals/share-promo-vid/share-promo-vid";
import { SocialSharingService } from "../../providers/social-sharing-service";
import { AuthorizationService } from "../../providers/authorization-service";

@Component({
  selector: 'page-home',
  templateUrl: 'home.html',
  providers: [VimeoService, SocialSharingService]
})
export class HomePage {

  constructor(private navCtrl: NavController,
              private vimeoService: VimeoService,
              private sharingService: SocialSharingService,
              private modalController: ModalController,
              private authService: AuthorizationService) {

  }


  //Used to display the promo video modal upon pressing share HisWord365 button
  public showSharePromoVidModal(){
    console.log(this.authService.token);
  }
}

Lastly the Service looks like this. (There is a part of the code where I do set the token but its not included for brevity)

export class AuthorizationService {

  private _token: string;
  private _refreshToken: string;
  
  //== Token
  get token(){
    return this._token;
  }
  //== Refresh Token
  get refreshToken(){
    return this._refreshToken;
  }
  
}

Take the “providers” out of your @Component decorator. Their presence causes those services to have the lifecycle of the component, which is not what you want.

Well the only service that I need to persist is my AuthorizationService though. Do I need to put all my services in my @NGModule then?

It seems that it does in fact share my data between the components if I set the data from the outside in. The second I do the reverse it fails to retain what has been set.

For example if I set my token field inside of one of my AuthServices functions like so

  //queries the database for an auth token so that we can log in to the application
  public signIn(usrnme: string, psswrd: string) : Observable<any>{

    let body = this.jsonToURLEncoded({ grant_type: "password", username: usrnme, password: psswrd });
    let options = new RequestOptions({ headers: this.headers });
    let signOnUrl = this.websiteUrl + this.signInUrl;

    this._token="Whats up";
    return this.http.post(signOnUrl, body, options)
      .map( this.simplifySignIn )
      .catch( this.simplifySignInError );

  }

When I retrieve the token from another component after I call sign up e.g.

public showSharePromoVidModal(){
	console.log(this.authService._token); 
}

It will not show “What’s Up”.

I honestly have no clue what is going on here.

Have you tried to put a console.log inside your provider’s constructor? Just to check if it’s rendered only once. But in any case that the provider’s constructor get’s called when you open the component, then it’s not a sharedProvider. Though it doesn’t make sense, try to change private into public in your component’s constructor. :slight_smile:

I think this is bad advice. The only properties that should be public in a component are the ones accessed by templates, and templates should not be directly referencing services. That should go via methods defined in the component, so that the service implementation can be decoupled from the template.

Agreed with that. :smile:

I keep on reviewing his code and I can’t see any reason why it’s happening on him. Wondering… :blush: