0

We need to display data from an external site in an iframe while also being able to listen for events.

I can get the iframe to render with the url that is returned from the API. Where is am stuck is with eventHandlers and messaging.

Specifically:

  1. Should I define channel in data? Or as a computed property? Does it matter?
  2. The code snippet for sending "port2 into the iframe" on the callback of the iframe element - How can I reference this callback in my vue template?
  3. How do I actually use the channel.port1.onmessage snippet? I'm assuming this is listening to any messages sent FROM the iframe in port2. Is this where I would call different functions based on the event.data.handlerName that shows up?

Here is the API documentation:

Use the MessageChannel API to create a new channel. You’ll use the two ports connected to the channel to communicate between your application and the UX inside the iframe.

const channel = new MessageChannel();

Send port2 into the iframe embedding the UX using the onLoad callback of the <iframe> element:

iframe.addEventHandler(“load”, (event) => {
    iframe.contentWindow.postMessage("", "*", [channel.port2]);
});

Now that the embedded experience has received port2, listen to events from the iframe on port1, the port you retained earlier:

channel.port1.onmessage = (event) => {
    // check event.data.handlerName and event.data.eventType,
    // and handle messages sent from the embedded UX
};

Here is my template.

<template>
  <div class="dashboard">
    <div class="dashboard__container">
      <div class="dashboard__container--header">
        <h1>Contractors</h1>
      </div>
      <div class="dashboard__container--body">
        <iframe 
          :src="iframaData"
          id="frame"
          ></iframe>
      </div>
    </div>
  </div>
</template>


<script>
import { mapState } from 'vuex'
import firebase from 'firebase/app';

export default {
  name: 'accountPayroll',
  data: () => ({ 
    iframaData: null,
    channel: '',
  }),
  methods: {
    createComponentSession() {
      console.log('fetching')
      const createComponentSession = firebase.functions().httpsCallable('createComponentSession')
      createComponentSession({
        id: this.currentUser.uid
      })
      .then(result => {
        if (result && result.data && result.data.url) {
          this.iframaData = result.data.url
          console.log(result.data)
        }
      })
    },
    sendPort2() {
      this.iframe.addEventHandler(event => {
        this.iframe.contentWindow.postMessage("", "*", [this.channel.port2]);
      });
    },
    message() {
      this.channel.port1.onmessage = (event) => {
        // return event.data.handlerName == "ONBOARDING"
        console.log(event)
      };
    }
  },
  computed: {
    ...mapState(['currentUser', 'userProfile']),
    channel1() {
      return this.channel.port1;
    },
    channel2() {
      return this.channel.port2;
    },
    iframe() {
      return this.$el.querySelector("iframe")
    }
  },
  created() {
    this.channel = new MessageChannel()
    this.createComponentSession()
  },
  mounted() {
    this.sendPort2()
    this.message()
  },
  beforeDestroy () {
    this.iframaData = null;
    delete this.iframeData;
  }
}

</script>

Any help would be much appreciated. Thanks!

Greg Fielding
  • 517
  • 3
  • 10
  • 26
  • 1
    The question isn't specific enough, see https://stackoverflow.com/help/how-to-ask . There's at least one mistake, `this.onLoad()`, this isn't how callbacks work. What's `src="???"` ? It's supposed to be child app that receives a message. `event` is https://developer.mozilla.org/en-US/docs/Web/API/MessageEvent object with event.data containing message payload. You may not need MessageChannel at all, as it makes it unnecessarily complicated, considering that a child is your app too, could use existing window message like bus https://stackoverflow.com/questions/52047205/ – Estus Flask Mar 05 '23 at 21:24
  • Thanks for the help. Yes I understand the post isn't specific enough. Configuring the API instructions into a vue template is confusing. Like you said, with vue, I might not even need messageChannel. I'm looking for advice for the right way to put this together. – Greg Fielding Mar 05 '23 at 22:19
  • 1
    The linked question is on-topic, it can be as simple as the answer shows – Estus Flask Mar 05 '23 at 23:02

0 Answers0