Events Broadcasting in ionic5

I am migrating my app from Ionic3 to 5.
First blocker I am finding is the events pipeline

I use events in the app for sending signals between views with Events. Now events is removed in 5 and I am looking for an alternative. How can I broadcast events in one view / page and create listeners for that specific message in others?

My previous code was similar to

  this.events.subscribe('system:phoneInfo', (systemInfo: string) => {
    Logger._phoneInfoString = systemInfo;
  });

where any view could call system:phoneInfo and the subscriber would do as said. My head does not wrap around how to distribute this over multiple views.

What I would do is to move everything into strongly-typed Observables that live in services. That being said, while you have the opportunity, may I please urge you to carefully audit every one of these situations with an eye to eliminating as many as possible? They are a recipe for spaghetti code that is really tough to maintain, extend, and test, because it is so hard to see what subtle interconnections exist between objects. In my experience, bugs lurk in crevices like this.

Do you have any example I could look into how to enable communication between views? Right now, I visualize it in my head that with observers each view instance would have to have a reference of another view stored it wants to talk to.

It would help if you could explain what they have to say to one another, in business-layer terms.

I came back to this, still no proper solution. What I have is a menu

<ion-app>
  <ion-split-pane contentId="main-content">
    <ion-menu contentId="main-content" type="overlay">
      <ion-content>
        <ion-list no-lines width="10">
          <ion-list-header>
            <h2>MyApp</h2>
          </ion-list-header>  
          <ion-menu-toggle auto-hide="true">
            <ion-item click='MainView.fooBar()'>
              Foo Bar
            </ion-item>
          </ion-menu-toggle>
    ....
    </ion-menu>
    <ion-router-outlet id="main-content"></ion-router-outlet>
  </ion-split-pane>
</ion-app>

that’s in app.components.html and app.components.ts . I would like the Foo Bar button to trigger the fooBar method on my MainView class that is shown in the router-outlet .

I am not sure how I can connect the event. I could catch the item click in a app.components.ts method, but how do I tell MainView to trigger fooBar from out of app.componets without the event library? fooBar does some UI stuff in the current view.

class MainView implements OnInit {
 fooBar(){
// do some UI stuff
}
}

I wish I knew more about what “does some UI stuff” means, but here’s the fundamental design problem I see here:

I spoke earlier about bugs living in crevices. If responsibility is clearly isolated, then a) we know what has to be tested, b) if something goes wrong, we know where to look, and c) it’s harder to break existing functionality by extension.

Your situation is not too dissimilar to the one that soured me completely on Ionic Events, and, frankly, hardened my resolve about getting rid of imperative thinking in web apps.

I had a toolbar, like the kind you see in modern office suite software. It contained a refresh button. When you clicked on the refresh button, whatever the main content pane was was supposed to go get the most up-to-date version of whatever data it was displaying.

This eventually became completely unwieldy. Some pages didn’t really have anything to refresh, which meant we had this button that didn’t always work. There isn’t any way to test whether an unrelated page is responding to such calls for action at a distance, so new pages would get added and there would be an omission or mistake in wiring up the refresh functionality. Some pages were specifically designed to look at a logically-consistent snapshot of information coming from many different sources, that the page itself wasn’t even always aware of. There isn’t any possible way for the page to even know what’s refreshable, let alone try to refresh it.

Furthermore, one thing that both Apple and Google agree on when it comes to UI design is that sidebars are for navigation - users expect them to provide ways of changing what the main pane is, not drilling down into making the main pane do X or Y.

I agree on the Apple and Google standpoint. But, in my case I want to really need to modify the state of main view to make an important user action in the app readily accessible. The menu shows only for this view so your one panel, multiple view situation is not happening. However, maybe the menu should be moved into the MainView.html instead of being in app.components.html ?

I meanwhile reimplemented my own event handler for this last night

import { Injectable } from '@angular/core';
import { Subject, Observable } from 'rxjs';

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

    static subject = new Subject<any>();

    static sendMessage(text){
        EventsService.subject.next(text);
    }

    static getMessage(): Observable<any>{
        return EventsService.subject.asObservable();
    }
}

If we agree that sidebar menus should be used for navigation, to determine which page is current, then I would look for someplace other than a sidebar menu to put this feature.

I don’t get the sense I’m going to convince you, here, though, and that’s OK.

No, I’m kinda set on this :smiley: But I really appreciate your feedback, always super helpful. :+1:

Maybe follow up question - I guess the menu does not have to live in the app.components.html as it’s shown in the examples… right? I think this is just a design flaw on my end that I used the sample codes to make it work and go from there.