Categories
Ionic RxJS Tutorials

From Ionic Event to Rxjs Subjects

My Ionic Expense application uses hammerjs to add touch gestures. This app has very little gestures, just couple of swipes when changing dates. So I tried to add them but they are only available in ionic/angular version 5. As soon I updated, the Ionic Events broke, hello to rxjs subjects.

Ionic Events are removed from ionic/angular version 5. See deprecation error

If you are more of a video person that I have also attached the video at the end of the article

Watch Video

For the final source code you can visit the Github repo

Github

Before RxJS Subjects

For years, Ionic Events made it so easier to manage the events. All you have to do is import the Events module Where ever you are in the app. While dispatching events, just provide it a name or channel name per se and that’s it. In order to consume it, just remember the name.

For instance you have to Component A emits and events, the code for it looks like

    dynamicPricing = true

this.events.publish('dynamic:Pricing', this.dynamicPricing);

Component B will consume it as follows;

    this.events.subscribe('dynamic:Pricing', (boolean) => {
    this.advancedTextField = boolean
})

RxJS Subjects

Subjects are like event emitters. In observables language they are observers as well as observables. You can subscribe to them and call next on them to feed new values.

We have some other variants of Subjects

TypesDescription
Behavior SubjectIt expects an initial value
Replay SubjectAs name suggests, it replays all previous values to
new subscriber even if previous values are missed
Async SubjectIt emits values only when it completed. So the
subscribers will get last value
Types of RxJS Subjects

For us the basic Subject will do the job, so let’s modify the existing code.

I created an example branch called events to subject. Here is the link to commit for the start of the tutorial. We have Home Component and Settings Component. Home component has a single text field that can either accepts the number or text based numberMode field property. The mode switching is controlled by ion-toggle in settings page.

Here the toggle in setting page acts a configuration for the whole app

The setting page here uses the ionic events as can be seen in the following picture

Settings page uses Ionic Events which need to replaces with rxjs subjects

The events is consumed in the home page as follows

    export class HomePage {
  numberMode = true

  constructor(private events: Events) {
    this.events.subscribe('dynamic:Pricing', data => {
      this.numberMode = data
    });
  }
}

Deprecation Warning

But we use events we got to see these messages in the browser console

A deprecation warning from angular cli that Ionic Event provider is deprecated and will be remove in next major release. Use other options like Observables or Redux
There is nice deprecation warning about Events usage

As we can see the console we see the deprecation error. The warning is so nice that it propose us two solutions.

  1. Observables
  2. Redux or any state management solution

We will go with the first one in this article

Solution

Let’s create a service using ionic cli

ionic generate service settings

This will help us generate a blank new service and place in the root folder. The file content are as follows

    import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class SettingsService {

  constructor() { }
}

Next we will be using behavior subject because we need a default value. Secondly we added the observable to consume the actual because original subject is kept private and lastly we need a method to update the subject observable.

    export class SettingsService {
  private numberSubject = new BehaviorSubject(true)
  numberMode$ = this.numberSubject.asObservable()

  constructor() { }

  updateNumberMode() {
    this.events.publish('dynamic:Pricing', this.numberMode);
  }}

}

Next let’s adjust the Settings and Home Component

The code of Settings Page becomes

    import { SettingsService } from '../settings.service';

@Component({
  selector: 'app-settings',
  templateUrl: './settings.page.html',
  styleUrls: ['./settings.page.scss'],
})
export class SettingsPage implements OnInit {

  numberMode: boolean;

  constructor(private events: Events, private settingsService: SettingsService) { }

  ngOnInit() {
    this.settingsService.numberMode$.subscribe(resp => {
      this.numberMode = resp
    })
  }

  updateNumberMode() {
    this.settingsService.updateMode(this.numberMode)
  }

}

We have imported a Setting Service and injected it in the constructor. Next we updated code in the ngOnInit lifecycle hook to use the new rxjs subjects. Same goes for the updateNumberMode.

Now let’s adjust the Home Component

    constructor(private events: Events) {
    this.events.subscribe('dynamic:Pricing', data => {
      this.numberMode = data
    });
  }

That’s these are the only lines we need to change. Nothing to be changed on the template or the html side

Conclusion

Before signing off, let’s remove the ionic Events imports and the deprecation error is gone. I have pushed the final code as a commit to the branch. But again, using this commit as a starting point. If you get in a problem than compare your code with this commit

Screencast

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.