2

I am new to ionic, angular and typescript. I have a variable "ar: AR" that I need in all pages, so I thought it is a good idea to make it a global variable. I do it like this:

First I define:

@Injectable()
export class AR {

 public roll: FR;

 constructor() {
   this.roll = new FR("test");
 } 

 set_roll(_roll) {
    this.roll = _roll;
 }

 get_roll() {
    return this.roll;
 }

}

Then I add the class as a provider in app.module.ts.

import { AR } from ...
@NgModule({
  ...
 providers: [ AR, ...]
 })

In app.compontents.ts I define a function:

export class MyApp {
rootPage:any = HomePage;

constructor(public ar: AR) {

  platform.ready().then(() => {
    ...
  }

}

activate(roll){
    this.ar.set_roll(roll);
   }

}

and in the app.html I define a button which should set this variable "ar" to a new value which is stored in an array named "myArray":

<ion-content>
    <ion-list>
          <ion-item *ngFor="let i of myArray (click)="activate(i)">
   </ion-list>
</ion-content>

However, the value of the global variable does not change. It always stays the inital value "test" defined in the constructor of the AR class.

It should be printed in another page:

import { AR } from ...;


@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {

    ar_name: string;

    constructor(..., public ar: AR) {
      this.ar_name = this.ar.get_roll().get_rollname();
    }

(get_rollname is a function of the AR class and simply returns a string.)

In the respective HTML:

 <ion-footer>
  <div> {{ar_name}} </div>
 </ion-footer>

What am I doing wrong?

Edit:

export class FR {

    private rollname: string; 

    constructor(rollname: string) {
      this.rollname = rollname
    }

    set_rollname(newName: string) {
       this.rollname = newName;
    }

    get_rollname() {
       return this.rollname;
    }

}
refle
  • 587
  • 3
  • 6
  • 19
  • can you add the code where you are actually showing the value in html? which component is it? – Suraj Rao Jan 10 '18 at 05:44
  • Thank you, I added the respective part :) So what am I doing wrong? – refle Jan 11 '18 at 14:57
  • Are you able to console log the value? And you have a typo in app.html.. missed a `"` – Suraj Rao Jan 11 '18 at 15:11
  • Try without innerhtml – Suraj Rao Jan 11 '18 at 15:13
  • how can I do it without "innerhtml"?? how do i get the value? and i still have to figure out where the consol log is written :D - i am still a newbe – refle Jan 11 '18 at 16:37
  • @refle like this ` {{ar_name}}` , but for the innerhtml you dont need to assign with the `this` you can assign directly as follows `[innerhtml] = "ar_name"` – Krsna Kishore Jan 12 '18 at 13:37
  • @ Webruster: Thank you. However, if I just use ' {{ar_name}}' I don't see the variable (it is plain HTML then...) so I need some kind of statement for angular, dont I? – refle Jan 15 '18 at 17:20
  • @refle i couldnt see the `get_rollname();` in your class you posted. ? – Krsna Kishore Jan 16 '18 at 05:43
  • @Webruster: The 'get_rollname();' function is a function of the 'FR' class. 'get_roll()' returns an FR-class object... I added the class in the question now. – refle Jan 16 '18 at 17:14
  • And yes, it still doesn't work, even if I replace the innerhtml-part with the {{...}} part. – refle Jan 16 '18 at 17:19
  • your `*ngFor` loop doesn't contain an ending quote. `*ngFor="let i of myArray` should be `*ngFor="let i of myArray"`. Also, where is the `myArray` object in your example? – RustyPiranha Jan 16 '18 at 23:21
  • Could the try to set and get it within the same component. Just to try if it works in that case. – Robin Dijkhof Jan 18 '18 at 22:37

4 Answers4

3

Thank you all for your help. I actually solved the whole thing by putting all the data arrays and respective functions in a provider. Like this all data and methods are available to all pages. USE PROVIDERS - it makes everything so much easier and simpler.

refle
  • 587
  • 3
  • 6
  • 19
2

Injectors can be lazily loaded async and thus there are times where there might be more than 1 instance of the injectable beacuse there are more than one injector. See here and here.

Perhaps this applies to you.

JGoodgive
  • 1,068
  • 10
  • 20
1

Another way might be to simple make the class a singleton.

class A {
    static instance = null;
    constructor() {
        if(A.instance) return A.instance;
        A.instance = this;
    }
}

I have not tried it with thie angular injectors but I am curious if it would work?

JGoodgive
  • 1,068
  • 10
  • 20
  • Why am I getting down voated? Please explain. – JGoodgive Jan 18 '18 at 23:23
  • Using a singleton is ridiculous. That is what a service is for. – Robin Dijkhof Jan 23 '18 at 11:40
  • What exactly makes it ridiculous? If something is really needed in all pages why not make it available globally, like an application state is? The benifit of injecting any thing is really only archieved when using interfaces which we are not. So we still have coupling between classes. – JGoodgive Jan 23 '18 at 12:34
  • Making something globally available can be done with a service. – Robin Dijkhof Jan 23 '18 at 14:50
  • Yes but an injectable service is only motivated when it is not an ambient functionality, we have need of lazy loading and/or we are using interfaces to facilitate testability and lowering the coupling of modules. In this case we are talking about ambient functionality without interfaces in which case none of that is applicable and we should be just fine with a singleton, which also can be lazily loaded since we use the constructor as the getter of the instance. A quick google gives me this which seem to agree: http://enterprisecraftsmanship.com/2016/05/03/singleton-vs-dependency-injection/ – JGoodgive Jan 23 '18 at 15:13
0

If you want to use a global variable, it would be best to work with ionic storage module.

See here: https://ionicframework.com/docs/storage/

If you rewrite yourself the AR provider, then not only can you access it globally (if you import he provider in one of your pages), but the saved data survives closing and opening the app.

Also notice that the get(key) method returns a promise (async). So you want to do something as

getRoll().then((data)=> {
 // your code
});

As you are a beginner, you might want to read about asynchronous code first.

PS: As I read from your answers above, you don't know how to console log. Just write console.log("") in your code and it will be put out in your terminal. I recommend watching the Ionic Crash Course on Youtube from the Ionic team.

halfer
  • 19,824
  • 17
  • 99
  • 186
J. Hesters
  • 13,117
  • 31
  • 133
  • 249
  • 2
    Storage is intended to save data persistently, so that it can be restored after an app has been shut down and restarted. This is a very bad fit if you just want to share data between some pages. – mbuechmann Sep 25 '18 at 14:09