Ionic 4 Passing data objects between pages

Ionic 4 has made passing objects between pages a pain in the arse, this is my workaround.

Problem

In Ionic 2 and 3, you could easily pass objects between pages when pushing pages, showing modals. In Ionic 4, they've changed the router to the Angular router. You can still pass an object to a modal, but not easily between pages when using navigateForward. My workaround for this is simple: A Service.

Solution

1) Make a singleton service called something like SharedDataService.

Add your properties to it and simply set them before loading your new page, then remove them when you're done on the new page if you need to.

For example, here's a recent one I made for an app:

import { Injectable } from '@angular/core';
import { Events } from '@ionic/angular';
import { Log, SettingsDetail, StorageUnit, StorageItem } from '../interfaces/model';

@Injectable()
export class SharedDataService {

    public pendingEventToFire: string;
    public log: Log;
   
    constructor(
        public events: Events
    ) {}

    setPendingEvent(e: string) {
        this.pendingEventToFire = e;
    }

    firePendingEvent() {
        if (this.pendingEventToFire != null) {
            this.events.publish(this.pendingEventToFire);
            this.pendingEventToFire = null;
        }
    }
    
    getLogCopy() {
        return JSON.parse(JSON.stringify(this.log));
    }
}

2) Make sure you then import it in your app.module.ts (or inject into your lazy loaded modules):

@NgModule({
  declarations: [
    ... blah blah
  ],
  entryComponents: [
    ... your pages here
  ],
  imports: [
    FormsModule,
    BrowserModule, 
    HttpClientModule,
    IonicModule.forRoot(), 
    RouterModule.forRoot(routes)
  ],
  providers: [
    ...
    SharedDataService,
    ...
    { provide: RouteReuseStrategy, useClass: IonicRouteStrategy }
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

Note: I don't use lazy loading because I find it's a pain and makes everything more unnecessarily complicated for practically zero benefit. Your mileage may vary. I just want my app code to be simple and easy to maintain.

3) Here's how I'd use it when I'm editing a Log (a custom object in my app) from a list page:

  edit(item?: Log, event?: Event) {
    if (event) { event.stopPropagation(); }
    this._SharedDataService.log = item;
    this.nav.navigateForward('/logsEdit');
  }

4) Then on my logsEdit page:

  getData() {  
    if (!this._SharedDataService.log) {
      return this.nav.navigateRoot('/')
    }
    this.log = this._SharedDataService.getLogCopy();
    this.isLoading = false;
  }  

Notice how I make a copy so that I can make edits to the object without saving, which then doesn't change the original item in my list page, unless I decide to save my changes.

Aside: note also that I've got a pendingEventToFire string that I use when I want to make sure some event happens when I go back to a particular page, or it regains focus. Another good use of the shared service.

Conclusion

Pretty simple and it works. Just remember to null out your objects when you're done.

Hope this helps,

D

Comments: