What would be the best way to store data that I can access across an entire app in Angular 2 and Ionic 2 - typescript.
For user information my initial thought was to
Using a provider to hold global data is working for me in Ionic 2 beta 6, and I believe it is the recommended practice in Angular 2.
Generate a provider from the command line: ionic g provider GlobalService
Notice how the generated service is decorated with @Injectable
Inject your service in the @App
class; you do this by declaring it in the providers array:
@App({
templateUrl: 'build/app.html',
providers: [GlobalService] ,
config: {} // http://ionicframework.com/docs/v2/api/config/Config/
})
This will create an single instance of your provider that is accesible on every page. Wherever you need to use it, do not declare in the providers array, but on the constructor of the Page:
@Page({
templateUrl: 'build/pages/new-page/new-page.html',
})
export class NewPage{
constructor(public globalService: GlobalService) {
}
someFunction(){
this.globalService.someGlobalFunction();
}
One way to do it would be to make class with all the properties that you need and configure as a singleton when you bootstrap the application.
Service:
import {Injectable} from 'angular2/angular2';
@Injectable()
export class Config {
constructor() {}
public get USERID(): string {
return "XCAMPLISHIOUS";
}
}
Bootstraping:
import {bootstrap} from 'angular2/angular2';
import {TaciIlieApp} from './app/taci-ilie';
import {Config} from './app/services/config/config';
bootstrap(TaciIlieApp, [Config]); // configuring the Config provider here will ensure a single instance is created
Usage:
import {Component, Inject} from 'angular2/angular2';
import {Config} from '../../services/config/config';
@Component({
selector: 'game',
templateUrl: 'app/components/game/game.html',
styleUrls: ['app/components/game/game.css'],
providers: [],
directives: [],
})
export class Game {
constructor(private config: Config) {
console.log(this.config.USERID);
}
In the official Ionic 2 forum I found that you should
Inject it into the @App itself, then import it in the @Page to use it.
This is because Ionic doesn't use the same process as Angular 2 for bootstrapping your app, and the @App decorator doesn't provide the ability to create singleton services that are automatically available to all pages and components in your application; therefore the logical use is to inject your service in both your App.ts and the Page in which you are going to use it... Well, this kinda should be the behavior... in my case (I am working with Ionic 2 beta 5) this doesn't work, if you do that and inject @App and your @Page with your service (both importing them and using the providers array, it will create two separate services, which in my case is not so good because I am setting values for my service in App.ts and retrieving those values in some of my pages. So, if you need Singleton behavior, the way to go for me was to create a singleton service using the ol' gang of four pattern this way..
In your Service...
export class Globals {
//----------------------------------------------------------------------------------------------
// Static (Singleton Implementation) Properties Section:
//----------------------------------------------------------------------------------------------
static instance : Globals;
static isCreating : Boolean = false;
//----------------------------------------------------------------------------------------------
// Private Properties Section:
//----------------------------------------------------------------------------------------------
private screenWidth : number;
private screenHeight : number;
//----------------------------------------------------------------------------------------------
// Constructor Method Section:
//----------------------------------------------------------------------------------------------
constructor()
{
if (!Globals.isCreating)
{
throw new Error("No se puede llamar a esta clase con 'new' - Utiliza getInstance()");
}
}
//----------------------------------------------------------------------------------------------
// (Singleton Implementation) getInstance() Method:
//----------------------------------------------------------------------------------------------
static getInstance() : Globals
{
if (Globals.instance == null)
{
Globals.isCreating = true;
Globals.instance = new Globals();
Globals.isCreating = false;
}
return Globals.instance;
}
//----------------------------------------------------------------------------------------------
// Properties Section (ScreenWidth):
//----------------------------------------------------------------------------------------------
getScreenWidth() : number
{
return this.screenWidth;
}
//----------------------------------------------------------------------------------------------
setScreenWidth(val) : void
{
this.screenWidth = val;
}
//----------------------------------------------------------------------------------------------
// Properties Section (ScreenHeight):
//----------------------------------------------------------------------------------------------
getScreenHeight() : number
{
return this.screenHeight;
}
//----------------------------------------------------------------------------------------------
setScreenHeight(val) : void
{
this.screenHeight = val;
}}
Then wherever you need to use it...
import {Globals} from './services/globals';
globals: Globals;
this.globals = Globals.getInstance();
ngOnInit()
{
// Device Dimensions:
let that : any = this;
screensize.get().then((result) => {
setTimeout(()=> {
that.globals.setScreenWidth(result.width);
that.globals.setScreenHeight(result.height);
},50);
},
(error) => {
// Do Nothing yet...
});
}
I have been a little verbose in explaining exactly how I did it because I know that like me, there are lots of developers still getting a grip in Ionic 2 and Angular 2, it costs tons of hours to learn a platform and with issues like this you can literally spend days trying to figure out things, I hope this solution work for you and btw, I know that it may be obsolete by now since Ionic 2 Beta 6 was just released, my advise is for you to test both solutions, first the one in the forum and if that one doesn't work, this one worked for me and I hope it may make things work for you as well.