Events not worked in ionic 6.1.0

import { Events} from ‘@ionic/angular’;

when i tried the previous import i receive next error

Module ‘"…/…/…/…/node_modules/@ionic/angular/ionic-angular"’ has no exported member ‘Events’.

1 Like

import { Events } from ‘ionic-angular’;

add “Events” under provider in app.module.ts

as ionic new release feedback, this feature is deprecated, i am not understand the concept of observable, i need to do service like events has key and value and allowed publishing and subscribing

RxJS is such an integral part of Angular that I think it would really improve your life if you studied it a bit. IMHO, Ionic Events never should have existed in the first place.

can you give example using observable like event, by creating small service with publish and subscribe function please, thank you

Below using “events.subscribe…” you can create the global function on any page and then you can call/trigger this function using event.publish…‘default and updatemenu is ths name of subscription’

//first global function on app.componant.ts

events.subscribe(‘session:default’, (flag) => {
// console.log(‘calling’);
this.userid=‘notactive’;
this.initializeApp();
});

//second global function on app.componant.ts

  events.subscribe('session:updatemenu', (flag) => {
    this.userid='active';
    this.initializeApp();
    //console.log('calling2');
});

from login.ts page you can call/trigger above function like below
if(active){
this.events.publish(‘session:default’);
}else{
this.events.publish(‘session:updatemenu’);
}

@sanjay100 thank you, i already used liked this, but this feature now is deprecated in new version, and i am looking for using observable

1 Like

Out of curiosity, when did Ionic 6.1.0 released?

A few days back, Ionic 5 was released. Can you please double-check the version and update your topic.

And by the way, Events are removed in Ionic 5. Please check in the breaking changes https://github.com/ionic-team/ionic/blob/45d03baf981d0e10eb1fe689908532adef2ba31d/BREAKING.md#events-1

You can use observables. For example, create a global service:

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

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

    private fooSubject = new Subject<any>();

    publishSomeData(data: any) {
        this.fooSubject.next(data);
    }

    getObservable(): Subject<any> {
        return this.fooSubject;
    }
}

Now, for example, you are subscribing to it in app.component.ts:

@Component({
    selector: 'app-root',
    templateUrl: 'app.component.html',
    styleUrls: ['app.component.scss']
})
export class AppComponent {

    constructor(private globalFooService: GlobalFooService) {
        this.initializeApp();
    }

    initializeApp() {
        // other code

        this.globalFooService.getObservable().subscribe((data) => {
            console.log('Data received', data);
        });
    }
}

Now, you just have to emit the event from some other component:

@Component({
    selector: 'app-home',
    templateUrl: 'home.page.html',
    styleUrls: ['home.page.scss']
})
export class HomePage {

    constructor(private globalFooService: GlobalFooService) {
    }

    onSomeButtonClick() {
        this.globalFooService.publishSomeData({
            foo: 'bar'
        });
    }
}

The similar you can do for namespaced events. Checkout my blog on this for quick solution https://medium.com/wizpanda/dealing-with-breaking-change-in-ionic-5-db3ba711dfcd

Cheers!

8 Likes

Ugh. I get that it’s probably well-intentioned, but anybody who follows that blog is just going to end up reinventing all the flaws of Ionic Events. As for the code you posted in this thread, I would suggest anybody interested in using it:

  • get rid of any: a major benefit of using Observables here is type-checking
  • not use providedIn: 'root' because it prevents mocking
  • actually return an Observable from getObservable(), because the whole point of gating it behind a method is to prevent unexpected access through the Subject interface
1 Like

@sagrawal thank you, you are right the solution by simulating the old events class with new service

1 Like

These are good points. I think the important thing to remember is that the events system that people (and I) have used up until now was extremely simple to understand and therefore use and maintain.

People don’t want to use a more (seemingly) complex way of achieving something if another does exactly the job it’s supposed to do.

I read your linked post on why events are not recommended, my rebuttal for the 2 points:

  • Typos: I have a list of events in an object so I can use them throughout e.g. myEvents.login_success: aka no typos ever.
  • Type safety: all my events are object checked at the receiving end and work fine. The code is pretty straightforward.

Just how I see it.

Shadow DOM is a classic example of this in IMHO - it brings all this lovely encapsulation benefit for web components - but then becomes a royal pain in the butthole for customising them, which is exactly what is so good and EASY about plain CSS.

2 Likes

Easy to start using, I’d agree, but you’ve got a steep hill to climb to convince me on “maintain”. When I come upon a new codebase (or an old one that I’ve simply forgotten all the details about) and need to add a new feature, I do my best to minimize my unwanted impact. Often the hardest part about that is figuring out what depends on what. A targeted Observable is easier to wrap my head around than a diffuse and frequently totally undocumented global Events dispatcher.

An important part of your point here is “that people have used up until now”, and that’s why I wish Events had never existed in the first place and advocated against using them years ago.

These are great ideas. I like it when my automated tools (language, compiler, IDE syntax hinting, &c) enforce things like this, though, and they can do a much better job of that with Observables than with Events. When humans have to enforce the conventions, we (OK, me at least) do a less reliable job of it. I’m curious, though, how you can “check an object at the receiving end” without using out-of-band information about the object, especially when there isn’t any checking at the sending end.

We’ve also got some selection bias going on here, because I’m primarily writing to people who want guidance about what strategies are going to make them more productive developers (note that those aren’t always the readers that I’m directly addressing). My programming style was largely forged by reading Usenet, specifically comp.lang.c, and I tried to stash away as many memories of when somebody asked “how do I X?” and somebody else would answer “here’s why you should Y instead” so that those voices would be in my head if I ever felt myself considering wanting to X.

So, with my community-forum-support-monkey-hat on, Events facilitate people who don’t know how or don’t want to go through manually setting up a safety net like you apparently have to just jump right in the ocean and write a bunch of spaghetti.

Imagine we’re having a parallel conversation about garbage collection and I say to you “who needs it? I keep a list of allocated memory blocks, and before I access any memory I make sure it hasn’t been freed”. Wouldn’t you tell me “great, but (a) you shouldn’t have to be doing all that and (b) don’t you still find accidental double disposal bugs or memory leaks”?

I see shades of this discussion in features like access control in language design. I like it. I miss it. I wish JavaScript had it. But yes, you could make the exact same argument against it: it’s a royal pain in the butthole to futz around in the innards of stuff, which is exactly what is so good and EASY about JavaScript’s “everything is just a bag of free-for-all, loosely typed junk that can all be modified freely at runtime” model.

At the end of the day, I like, use and advocate for things that I think make it harder for me to do things I will end up regretting later, on the assumption that they’ll make you more productive as well. I dunk on things and habits that I think make it easier for me to write code that I’ll hate in the future.

Thank’s a lot, the fastest way for me to map my data i newly push to what i have on my database

1 Like

I think i am getting a similar error.

  The Ionic CLI will exit. Please check any output above for error details.
Mac-Air:iconic-app username$ 
  [Restored 22. Apr 2020 at 11:55:54]
Last login: Wed Apr 22 11:41:36 on console
Mac-Air:iconic-app username$  ionic serve

> ng run app:serve --host=localhost --port=8100
[ng] chunk {main} main.js, main.js.map (main) 2.02 kB [initial] [rendered]
[ng] chunk {polyfills} polyfills.js, polyfills.js.map (polyfills) 154 kB [initial] [rendered]
[ng] chunk {runtime} runtime.js, runtime.js.map (runtime) 6.15 kB [entry] [rendered]
[ng] chunk {styles} styles.js, styles.js.map (styles) 94.1 kB [initial] [rendered]
[ng] chunk {vendor} vendor.js, vendor.js.map (vendor) 339 kB [initial] [rendered]
[ng] Date: 2020-04-22T10:06:16.564Z - Hash: f3db0ef1e42df73f8bdc - Time: 15207ms
[ng] ERROR in src/app/address-pages/addresses/addresses.page.ts:5:42 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 5 import { ModalController, NavController, Events } from '@ionic/angular';
[ng]                                            ~~~~~~
[ng] src/app/app.component.ts:3:35 - error TS2305: Module '"../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 3 import { Platform, NavController, Events, ModalController, MenuController } from '@ionic/angular';
[ng]                                     ~~~~~~
[ng] src/app/cart/cart.page.ts:6:25 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 6 import { NavController, Events, ModalController, ActionSheetController } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/downloads/downloads.page.ts:3:25 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 3 import { NavController, Events } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/home-pages/home/home.page.ts:2:10 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { Events, IonSlides } from '@ionic/angular';
[ng]            ~~~~~~
[ng] src/app/home-pages/home10/home10.page.ts:2:25 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, Events } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/home-pages/home2/home2.page.ts:3:22 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 3 import { IonContent, Events } from '@ionic/angular';
[ng]                        ~~~~~~
[ng] src/app/home-pages/home3/home3.page.ts:2:10 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { Events, IonSlides } from '@ionic/angular';
[ng]            ~~~~~~
[ng] src/app/home-pages/home4/home4.page.ts:3:25 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 3 import { NavController, Events } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/home-pages/home5/home5.page.ts:2:25 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, Events } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/home-pages/home6/home6.page.ts:2:25 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, Events, IonContent } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/home-pages/home7/home7.page.ts:2:25 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, Events, IonContent, IonSlides, IonInfiniteScroll } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/home-pages/home8/home8.page.ts:2:25 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, Events } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/home-pages/home9/home9.page.ts:2:25 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, Events, IonContent, IonInfiniteScroll } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/intro/intro.page.ts:2:25 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, Events } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/app/modals/login/login.page.ts:4:42 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 4 import { ModalController, NavController, Events, NavParams } from '@ionic/angular';
[ng]                                            ~~~~~~
[ng] src/app/modals/scratch-card/scratch-card.page.ts:2:36 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, NavParams, Events, PopoverController } from '@ionic/angular';
[ng]                                      ~~~~~~
[ng] src/app/modals/select-country/select-country.page.ts:3:27 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 3 import { ModalController, Events, IonSearchbar, NavParams } from '@ionic/angular';
[ng]                             ~~~~~~
[ng] src/app/modals/select-zones/select-zones.page.ts:2:53 - error TS2305: Module '"../../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { ModalController, NavParams, NavController, Events } from '@ionic/angular';
[ng]                                                       ~~~~~~
[ng] src/app/news/news.page.ts:2:44 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { IonInfiniteScroll, NavController, Events } from '@ionic/angular';
[ng]                                              ~~~~~~
[ng] src/app/notifications/notifications.page.ts:2:63 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { IonInfiniteScroll, NavController, PopoverController, Events } from '@ionic/angular';
[ng]                                                                 ~~~~~~
[ng] src/app/product-detail/product-detail.page.ts:2:42 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, ModalController, Events } from '@ionic/angular';
[ng]                                            ~~~~~~
[ng] src/app/products/products.page.ts:2:67 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { IonInfiniteScroll, IonContent, IonSlides, NavController, Events, ActionSheetController, MenuController } from '@ionic/angular';
[ng]                                                                     ~~~~~~
[ng] src/app/settings/settings.page.ts:2:27 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { ModalController, Events, Platform, NavController } from '@ionic/angular';
[ng]                             ~~~~~~
[ng] src/app/thank-you/thank-you.page.ts:2:25 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 2 import { NavController, Events } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/components/categories/categories.component.ts:4:25 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 4 import { NavController, Events } from '@ionic/angular';
[ng]                           ~~~~~~
[ng] src/components/product/product.component.ts:3:27 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 3 import { ToastController, Events, ModalController, NavController } from '@ionic/angular';
[ng]                             ~~~~~~
[ng] src/providers/config/config.service.ts:9:20 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 9 import { Platform, Events } from '@ionic/angular';
[ng]                      ~~~~~~
[ng] src/providers/shared-data/shared-data.service.ts:13:37 - error TS2305: Module '"../../../node_modules/@ionic/angular/ionic-angular"' has no exported member 'Events'.
[ng] 13 import { Platform, ToastController, Events, AlertController } from '@ionic/angular';
[ng]                                        ~~~~~~

[INFO] Development server running!
       
       Local: http://localhost:8100
       
       Use Ctrl+C to quit this process

[INFO] Browser window opened to http://localhost:8100!



Injectable service

import {Injectable} from ‘@angular/core’;
import {Subject, Subscription} from ‘rxjs’;

@Injectable({
providedIn: ‘root’
})
export class Events {

private channels: { [key: string]: Subject<any>; } = {};

subscribe(topic: string, observer: (_: any) => void): Subscription {
    if (!this.channels[topic]) {
        this.channels[topic] = new Subject<any>();
    }

    return this.channels[topic].subscribe(observer);
}

publish(topic: string, data: any): void {
    const subject = this.channels[topic];
    if (!subject) {
        // Or you can create a new subject for future subscribers
        return;
    }

    subject.next(data);
}


destroy(topic: string): null {
    const subject = this.channels[topic];
    if (!subject) {
        return;
    }

    subject.complete();
    delete this.channels[topic];
} 

}

Function call

1. Change the imports

Before

import {Events} from 'ionic-angular';

After

import {Events} from '../your/path/to/service/events';

2. Changes in the subscribe method

Before

events.subscribe('user:created', (user, time) => {
    console.log('Welcome', user, 'at', time);
});

After

this.events.subscribe('user:created', (data: any) => {
    console.log('Welcome', data.user, 'at', data.time);
});

3. Changes in the publish method

Before

this.events.publish('user:created', someUserInstance, Date.now());

After

this.events.publish('foo:user:logged-out', {
    user: someUserInstance,
    time: new Date()
});

4. To Unsubscribe

const subscription = this.events.subscribe('user:foo:created', (data: any) => {
    // your logic
});

Once you are done, you can do this-

subscription.unsubscribe(); 
2 Likes

Here is the service, import it as you wish

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

export type EventHandler = (...args: any[]) => any;
@Injectable({
  providedIn: 'root',
})
export class Events {
  private c = new Map<string, EventHandler[]>();

  constructor() {
  //   console.warn(`[DEPRECATION][Events]: The Events provider is deprecated and it will be removed in the next major release.
  // - Use "Observables" for a similar pub/sub architecture: https://angular.io/guide/observables
  // - Use "Redux" for advanced state management: https://ngrx.io`);
  }
  /**
   * Subscribe to an event topic. Events that get posted to that topic will trigger the provided handler.
   *
   * @param topic the topic to subscribe to
   * @param handler the event handler
   */
  subscribe(topic: any, ...handlers: EventHandler[]) {
    let topics = this.c.get(topic);
    if (!topics) {
      this.c.set(topic, topics = []);
    }
    topics.push(...handlers);
  }

  /**
   * Unsubscribe from the given topic. Your handler will no longer receive events published to this topic.
   *
   * @param topic the topic to unsubscribe from
   * @param handler the event handler
   *
   * @return true if a handler was removed
   */
  unsubscribe(topic: string, handler?: EventHandler): boolean {
    if (!handler) {
      return this.c.delete(topic);
    }

    const topics = this.c.get(topic);
    if (!topics) {
      return false;
    }

    // We need to find and remove a specific handler
    const index = topics.indexOf(handler);

    if (index < 0) {
      // Wasn't found, wasn't removed
      return false;
    }
    topics.splice(index, 1);
    if (topics.length === 0) {
      this.c.delete(topic);
    }
    return true;
  }

  /**
   * Publish an event to the given topic.
   *
   * @param topic the topic to publish to
   * @param eventData the data to send as the event
   */
  publish(topic: string, ...args: any[]): any[] | null {
    // if(topic=="refresh"){
    //   topic = topic+''+args
    // }
    // console.log(topic);
    const topics = this.c.get(topic);
    if (!topics) {
      return null;
    }
   
    return topics.map(handler => {
      try {
        return handler(...args);
      } catch (e) {
        console.error(e);
        return null;
      }
    });
  }
}
usage
this.events.publish(" some tips");

// subscribe
this.events.subscripribe("name" , (data)=>{

})