Ben
Ben

Reputation: 353

Communicating from an Inertiajs page in an iFrame to parent component

I'm working on a Laravel/InertiaJS/Vue3 project.

I have a Vue component that loads an iFrame which, in turn, loads an Inertiajs page.

When that InertiaJs page refreshes I want to sent a message to the parent component.

It seems the best way to do this is using postmessage()

        router.visit(route('conversation.show',id),{
            onSuccess: event =>{
                window.top.postMessage('somemessage')
            }
        });

and a corresponding listener in the parent:

    onMounted(() => {
        window.addEventListener('message', methods.receiveMessage)

    });

Before I continue with this, is there a more Inertia/Vue best-practise way to do this? e.g. using state management or some more secure way to communicate?

TIA

Upvotes: 0

Views: 259

Answers (1)

Ben
Ben

Reputation: 353

In the end I wrote a little composable to post and listen to post messages:

import { onBeforeUnmount } from 'vue';

const tag = 'usePostMessage';

export const usePostMessage = () => {

    //function to post a new message from the iframe
    const postMessageFromIframe = (message, targetOrigin = window.top.location.origin) => {
        window.top.postMessage({from: tag, payload : message}, targetOrigin);
    };

    //listen for messages from child frame
    const listenToPostMessage = (actions, callback) => {

        const messageHandler = (event) => {
            //confirm message
            if (event.source.origin === window.top.origin && event.data.from === tag) {
                for (const action of actions){
                    if (action === event.data.payload.action){
                        callback(event.data.payload);
                    }
                }

            }
        };

        window.addEventListener('message', messageHandler);

        // Cleanup the event listener when the component is unmounted
        onBeforeUnmount(() => {
            window.removeEventListener('message', messageHandler);
        });
  };

  return { postMessageFromIframe, listenToPostMessage };
};

Then from inside the iframe:

    const {  postMessageFromIframe } = usePostMessage();
    postMessageFromIframe({action:'resizeFrame'});

And outside the iframe:

    const {  listenToPostMessage } = usePostMessage();
    listenToPostMessage(['mounted'],methods.onLoaded);
    listenToPostMessage(['resizeFrame'],methods.adjustIframeSize);

Upvotes: 0

Related Questions