0

I created a simple ionic app that allows users to book services. The user would select a service category, choose a service(s) then navigate to a form to complete the booking.

I've setup an event bus using tiny emitter since the project uses vue 3 with the composition api. The data emits as expected however when navigating to the booking form the listener is not triggered.

The expected behaviour is to get the selected service(s) and send it along with the rest of the booking info to a REST api.

eventBus.js

import { TinyEmitter } from 'tiny-emitter';
const emitter = new TinyEmitter();
const eventBus = () => {
    return { emitter };
};
export default eventBus;

Service.vue

// template

<ion-button routerDirection="forward" routerLink="/booking" @click="sendEvent">Book Now</ion-button>

// script

import eventBus from './eventBus';

export default {
  ...
  setup() {
    ...
    const sendEvent = () => {
      eventBus().emitter.emit('selected-service', 100) // the real code emits an array
    }
    return { sendEvent }
  }

}

Booking.vue - Nothing happens in the console log

<script>
...
onMounted(() => {
  eventBus().emitter.on('selected-service', (payload) => {
    console.log('listener', payload);
  })
})
</script>

I know this works in a regular Vue 3 project but I'm not sure why it's not working with ionic.

Things I've tried

UPDATE

I noticed the listener gets called when I navigate off the booking page then back to it. So if I go from service details -> booking -> back to service details -> booking it triggers the bus and the payload is captured.

chrome dev tools

isherwood
  • 58,414
  • 16
  • 114
  • 157
carlhandy
  • 315
  • 1
  • 8
  • 22
  • I've created a quick start repo that replicates this issue: https://github.com/carlHandy/Ionic5-Event-Bus – carlhandy May 24 '21 at 17:50

3 Answers3

0

This may be a framework level bug. I've spoken to the Ionic team via twitter and was advised to use query params instead so that's the route I took.

enter image description here

carlhandy
  • 315
  • 1
  • 8
  • 22
0

may be rxjs helps you

import { Subject } from 'rxjs';
private newProduct = new Subject<any>();

publishNewProduct() {
 this.newProduct.next();
}

subscribeNewProduct(): Subject<any> {
 return this.newProduct;
}
Rahul Jograna
  • 856
  • 10
  • 9
0

Just had the same problem, to make it worse, in my case the bug was intermittent and only present if the dev tools console was closed. Opening the dev tools or using alerts would result in the component being rendered in time to receive the event.. I almost lost my sanity over it.

In my case using a watcher on the a prop using immediate: true was the cleanest solution.

I think this bug is really nasty since global events support have been removed from Vue2 and the Vue3 upgrade docs explicitly suggest to use tiny emitter to achieve it.

This leads to weird behaviors and bugs that are almost impossible to trace back. For this reason, I think the global event pattern should be avoided as much as possible.

As a final note if it can help someone, this is how I ended up being able to use console logs to trace the problem back to the global event bus:

const logs = []
app.config.globalProperties.$log = function () { logs.push(arguments) }
window.viewlogs = () => {
  for (let i = 0; i < logs.length; i++) {
    console.log.apply(window, logs[i])
  }
}

Once the bug occured I could open the dev tools and view logs using window.viewlogs()

tony19
  • 125,647
  • 18
  • 229
  • 307
h3.
  • 10,688
  • 15
  • 51
  • 54