[SOLVED] Ionic v2 - Share a model accross tabs


#1

I’m creating a form which is separated in several tabs.

I would like to know if it’s possible to share the same model between all tabs ?


#2

I’m not exactly sure what your asking, but if you create an Injectable class you should be able to use it in every single page that represents a single tab, and if you store values in the injected instance they should be available across all tabs.


#3

Thank you for your help.

In fact, I solved my problem last night. Here is my solution :

I have a creating form separated in 5 tabs for UI simplicity. Due to the fact that in Ionic2, each tab is a separated page, i wanted to create my model in the main page, then share it in each tab/page. When the user click on save, it calls the save method on the main page.

  • CreatePage -> Initalize my model + contains global saveModel() method
    • Tab1Page
    • Tab2Page
    • Tab3Page

My solution was to pass params to each tab which was my model + a reference to my saveModel() method.

  • CreatePage.js
constructor() {
  this.myModel = {
    // [...]
  };
}

saveModel() {
  // [...]
}
  • CreatePage.html
<ion-tabs>
  <ion-tab tabTitle="Tab1" [root]="myTab1" [rootParams]="{ model: myModel, onSave: saveModel }"></ion-tab>
  <!-- [...] -->
</ion-tabs>
  • Tab1Page.js
constructor(navParams) {
  this.model = this.navParams.get('model');
  this.saveModel = this.navParams.get('onSave');
}
  • Tab1Page.html
<ion-navbar *navbar secondary>
  <ion-title>Tab 1</ion-title>
  <ion-buttons end>
    <button (click)="saveModel()"> <!-- Here i use my global function -->
      <ion-icon name="checkmark"></ion-icon>
    </button>
  </ion-buttons>
</ion-navbar>
<!-- [...] -->
<ion-textarea [(ngModel)]="model.notes"></ion-textarea> <!-- Here i use my global model -->

It works perfectly ! Hope that it helps somebody :thumbsup:


#4

Hello there!
Thanks so much @guillaume_r for coming back to provide some info! It was really useful!

I am having an issue though and it would be great if you (or someone else) could help:
I create a model in tabs.ts then pass it to tab1 and tab2. This works ok and values from the newly created model are shared between the two tabs (changing in one is directly reflected in the other).

The problem arises when I need to load from storage (I use localforage and have a dataService.localGetItem(‘model’) to load a saved model in tabs.ts. However, tab1 (the home page) only gets an undefined model and it is not updated after the promised is completed. Tab 2 which is click later (after tabs.ts has loaded and passed the correct model) works fine.

Any help would be immensely appreciated as I’ve spent many hours to no success :confused:
Thanks!

Code parts:
in tabs.ts:

this.myDay = this.dataService.localGetItem('CURRENT_DAY').then((value) => {
      this.myDay = value;
      console.log(this.myDay);
    }); 

in tab1 and tab 2:
this.myDay = this.navParams.get(‘day’);


#5

Bold part no good, very bad. Make it go away.


#6

Hahaha yeah I know @rapropos , I also tried without but then the part in tab1.ts that grabs the model from the navParams

this.myDay = this.navParams.get(‘day’);

gets executed before the localGetItem is done grabbing it from storage in tabs.ts :confused: So the whole thing crashes because in tab1.html I display something from myDay (say myDay.element) that is not available to the page at loading.


#7

The recommended Angular 2 approach for sharing a model is to make an @Injectable class, which you then specify as a Provider when bootstrapping your app (app.ts)… Then any class/page etc which need to access this takes that as a parameter in it’s constructor, this is Dependency Injection.

That way you don’t create and manage the model yourself, Angular does it for you on starting your app. You could load saved state from local storage etc in you app class’ (app.ts) ngOnInit method.


#8

Thanks @webprofusion for the info. Since I’m very new to this, could you please elaborate a bit on how I should go about doing that? It would help immensely :slight_smile:

Edit:
Also, I’m not sure how it would work out. The model would have to be created at some point - so if it’s an @Injectable I guess it would be created in app.ts. But then how would this same instance be passed to the other pages to make sure everything accesses the same data? I’m getting confused :confounded::sweat_smile:


#9

@Dimitrios

  • Create new file to be injected (e.g: myModel.ts)

@Injectable() export class myModel { myModel:any saveModel:any constructor() { ... } //Put Getter Setter method or other method as necessary here

  • Add this as provider on your app.ts bootstrap (if you use beta.8 put it on ionicBootstrap code) e.g:

import {myModel} from ‘path/to/myModel’

ionicBootstrap(MyApp,[myModel])

  • On your tabs.ts import it then you can use it as necessary

import {myModel} from ‘path/to/myModel’

constructor(mymod: myModel)
{
//call getter from your model
this.model = myModel.getModel();
}

Note :
On my case, I didn’t include @Injectable() on my so called myModel class but yet I can access it throughout my entire app using code above.


#10

Awesome @wienzzz ! Thanks a lot! This is precisely what I did and it’s true, the model works correctly (I found this article interesting on Angular 2 Injectables: http://jbavari.github.io/blog/2015/10/19/angular-2-injectables/ ).

Now I need to implement what this whole thing started about:

  • I need to check storage, retrieve object with label “CURRENT_DAY
  • Check if the date on object CURRENT_DAY matches today’s date
  • If yes, assign this loaded object to the myDay model that is shared everywhere
  • Otherwise leave the newly created model empty to be changed by options in the tab pages

My question lies in where should I use the dataService to check storage? I’m looking into what @webprofusion mentioned with ngOnInit to see if it’s the right way.

One more thing. Now my model is created automatically - I guess during application bootstraping. What if I want to pass arguments in the constructor for model creation? Where should those go?

Thanks for the help!