als9xd
als9xd

Reputation: 854

Vue event bus await mount

I have a Map component which initializes leaflet on the DOM like so:

Map.vue

<template>
  <div ref="map"/>
<template>
<script>
import * as L from 'leaflet';
import mapEventBus from '../event-buses/map.vue';

export default {
  mounted(){
    const map = L.map(this.$refs.map);
    mapEventBus.$on('add-marker',(newMarker) => {
      newMarker.addTo(map);
    });
  }
}
</script>

And then I have another component which needs to add a marker that is built on the components creation.

OtherComponent.vue

<template>
  <div/>
</template>
<script>
import mapEventBus from '../event-buses/map.vue';
export default {
  created(){
    mapEventBus.$emit('add-marker',L.marker([51.5, -0.09]));
  }
}
</script>

Because the map is initialized after the OtherComponent has already tried emitting to the event bus, the event is never fired. What would be the best way to "await" for the map to be initialized and then add the marker to the map. I though about having a "cache" of pending markers that is added on the map creation but that seems clunky.

Example:

https://codesandbox.io/s/2ov71xnz3r

Upvotes: 1

Views: 2222

Answers (1)

Trent
Trent

Reputation: 3103

OK, so you've got a little chicken and egg problem there. You have an element you need to update via refs (some way to hack data into a 3rd party plugin), but you get the data BEFORE you mount the HTML.

What you need to do is separate out the immediate catch into a data variable, then on mount, check to see if it exists and if so update the HTML element.

I'm not answering your question above, because the problem is simplified in the codesandbox example you provided.

Here is the solution based on that:

https://codesandbox.io/s/3rnyp31n4p

<script>
import { EventBus } from '../eventBus.js'

export default {
  data: () => ({
    immediateMessage: null
  }),
  beforeCreate() {
    EventBus.$on("immediate-message", message => {
      this.immediateMessage = message;
    });
  },
  mounted() {
    if (this.immediateMessage) {
      this.$refs.immediateMessageEl.innerHTML += this.immediateMessage;
    }
    EventBus.$on("delayed-message", message => {
      this.$refs.delayedMessageEl.innerHTML += message;
    });
  }
};
</script>

Note, the beforeCreate() binds to the event and sets a variable, then we use that variable once the DOM is mounted.

Check out lifecycle hooks page for more info https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram

This is definitely not the most elegant solution, but will definitely get you going.

Upvotes: 1

Related Questions