How can i use global variables on ionic 2?
Which can be access anywhere between pages and the views like on ionic 1.
declare var socket: any;
import {App,Page, IonicApp, Platform, Storage, SqlStorage} from 'ionic/ionic';
@App({
templateUrl: 'build/app.html'
})
Edit app.js .
declare socket var on top . You can access āsocketā variable in other pages .
This is the only way to declare global variable? if I have 10 global var of different types then I have to declare all variable one after another at app.ts?
declare var socket: any;
declare var push: any;
declare var username: any;
import {App,Page, IonicApp, Platform, Storage, SqlStorage} from āionic/ionicā;
@App({
templateUrl: ābuild/app.htmlā
})
I think it depends on what you want to do really but take a look at the Conference app here and have a look at how the favourites variable is maintained in there with getters and setters etc and shared across multiple components using the user-data provider.
Wellā¦ if using webpack you could declare them from the webpack.config.js
but then you would be tied to webpack until you declare those variables in your code, also itās not a recommended way of doing it since those variables definition would be in the config of the build process and not in your source code, which makes way harder to understand the code since you canāt tell where the hell those variables come from unless youāre the one that made the variables, tough is a good step for polyfills and libraries that need global scope like Chart.js.
In Ionic 2, we have ES6 modules, and having global variables isnāt really recommended. In fact, itās big anti-pattern with modules
@richardshergold is pointing you in the right direction. Having a dedicated data-store class instead is what you should be doing. This keeps things nice and separated and you can reason about where things are coming from.
Hi am really getting an headache on trying to understand how global variable works in ionic 2 ā¦ or how we achieve the same thing.
I read on stackoverflow that some suggest different ways becuz Angular 2 syntax is somehow changing recently, I also read, some mention BehaviorSubjectā¦ but I dun understand how it worksā¦ or does it work in ionic 2.
I come to realise thereās nothing like $rootScope anymore in ionic2, but I still cant manage to understand how.
- Say, I was trying to use ngSwitch to cater an app with mutliple language.
- I register a service to detect User Language on default (while allowing them to change it in a dropdown menu).
- in ionic 1 I just do the detection at the beginning and store it to a variable in the rootScope, users may change and alter the variable.
- ngSwitch will watch the variable and switch language content (for some reason my users need to be able to switch the language anytime quickly).
soā¦ how do I do this in ionic2? declaring variable in the app.ts doesnt workā¦ I triedā¦
Hi am really getting an headache on trying to understand how global variable works in ionic 2 ā¦ or how we achieve the same thing.
I read on stackoverflow that some suggest different ways becuz Angular 2 syntax is somehow changing recently, I also read, some mention BehaviorSubjectā¦ but I dun understand how it worksā¦ or does it work in ionic 2.
I come to realise thereās nothing like $rootScope anymore in ionic2, but I still cant manage to understand how.
- Say, I was trying to use ngSwitch to cater an app with mutliple language.
- I register a service to detect User Language on default (while allowing them to change it in a dropdown menu).
- in ionic 1 I just do the detection at the beginning and store it to a variable in the rootScope, users may change and alter the variable.
- ngSwitch will watch the variable and switch language content (for some reason my users need to be able to switch the language anytime quickly).
soā¦ how do I do this in ionic2? declaring variable in the app.ts doesnt workā¦ I triedā¦
Look at ng2-translate. There is an Ionic sample in the README.
thanks @rapropos I will try to make sense of that.
It looks promising on creating some mutli-language app.
However I am using multiple JSON to load some sort of complicated ancient text content to the viewā¦
It is hard to explain, but it seems a bit different from just switching between language.
I really need NgSwitch to get working to solve the problem in the simplest manner.
So I really really reallyā¦ want to know how to get it working, to store and change a variable and bind it with content.
@richardshergold covered that upthread with links to exactly where to look in the conference app.
How about storing your globals in a singleton class? As in:
- make a module for your globals, have it contain one class that has all the āglobalsā you need.
- use the class as a singleton by decorating it with
@Injectable
and including it inapp.ts
and in itsionicBootstrap()
call - include the class anywhere you need a global
Done!
Thanks @doron
I was sort of trying to achieve it in a similar way by setting up a āglobalsā class/service with Injectable.
Then, I face a problem, while the variables are being updated, the changes were not known real-time by other component. I ended up using an āemitā function to get it done by triggering an event.
Not sure if this is the proper way of doing it, but it worked.
Yes, @ultradryan, thatās exactly what I was suggesting. I also used this (injectable provider class) solution and had the same problem - that some variables were not being detected as changed.
That turned out to be related to zone.js and angular2 change detection.
One (probably terrible) hack that solved things and always worked for me was to set the variable inside a setTimeout()
(or similar) call because that triggers the angular2 change detection. So I did:
In the provider, injectable class that provides a variableās value to another:
instead of this:
this.memberVariable = value;
i had this:
setTimeout(this.memberVariable = value);
and the change-detection issue went away.
I think this is a hack and at some point Iāll look more into improving on it because I dislike hacks, but it works.
I used this method for access to host variable via provider e.g.
in app.ts top
declare var host : āhttp://xxxā ;
in provider class :
this.http.get(host+ā/api/r/lstā)
But : TypeScript error: path Error TS2304: Cannot find name āhostā.
@mhartington @richardshergold can you help us (newbies) create ābest practiceā once and for all to manage global variables in ionic 2? (I know Iām bumping the thread but itās worth it).
I checked the Conference App as suggested by @richardshergold and looked up the āfavoritesā variable (not favourites you made a typo ). And there seem to be a user-data provider in the user-data.ts file.
So I did my own provider:
global-vars.ts:
import { Injectable } from '@angular/core';
import { Events } from 'ionic-angular';
import { Storage } from '@ionic/storage';
@Injectable()
export class GlobalVars {
_vars: Array<{name: string, value: any}>;
constructor(
public events: Events,
public storage: Storage,
) {
console.log('Hello GlobalVars Provider');
}
varExist(varName: string): boolean {
return (this._vars.indexOf(varName) > -1);
};
addGlobalVar(varName: string, value: any): void {
this._vars.push({
name: varName,
value: value
});
};
removeGlobalVar(varName: string): void {
let index = this._vars.indexOf(varName);
if (index > -1) {
this._vars.splice(index, 1);
}
};
}
and in a component,
weightlevel.ts:
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { ComparePage } from '../compare/compare';
import { ViewChild } from '@angular/core';
import { Slides } from 'ionic-angular';
import { LocalStorageService } from 'angular-2-local-storage';
import { GlobalVars } from '../../providers/global-vars';
@Component({
selector: 'page-weightlevel',
templateUrl: 'weightlevel.html'
})
export class WeightlevelPage {
name: string;
constructor(
public navCtrl: NavController,
public navParams: NavParams,
private localStorageService: LocalStorageService,
public globalVars: GlobalVars,
) {
console.log("Executing Weightlevel.ts");
this.name = 'Max';
this.globalVars.addGlobalVar("isWebIntegration", false);
}
@ViewChild(Slides) slides: Slides;
ionViewDidLoad() {
console.log('ionViewDidLoad WeightlevelPage');
}
goToSlide() {
this.slides.slideTo(2, 500);
}
}
Can you help me finish this code? Itās not working for now.
Thanks
I think this approach is overly generic, and loses you lots of important compile-time checking, IDE assistance, and self-documentation. If you have a global isWebIntegration
boolean, say so. Explicitly put isWebIntegration: boolean
in your provider (or expose something that provides a Promise<boolean>
if you wish it to be seamlessly integrated with backing storage).
I am not sure I get what you say. Can you code it ?
Obviously there are many different options depending on design decisions, but hereās one:
@Injectable()
export class AppContext {
ready: Promise<any>;
private _isWebIntegration: boolean;
constructor(private _storage: Storage) {
this.ready = Promise.all([
this._storage.get('isWebIntegration').then((wip) => this._isWebIntegration = wip),
// &c &c for other similar stuff
]);
}
// don't call any of these until this.ready resolves
isWebIntegration(): boolean {
return this._isWebIntegration;
}
setWebIntegration(wip: boolean): Promise<any> {
this._isWebIntegration = wip;
return this._storage.set('isWebIntegration', wip);
}
}