javascriptreactjsiframedom-eventsiframe-app

How to trigger 'beforeunload' event from within an IFRAME


I have an application (name it B) which is being embbeded in an Iframe by another main application (Name it A or parent).

So: App A--                     // domain of A: https://mydomain/mainApp
           |___ App B in Iframe // domain in B: https://mydomain/appB

Problem is: Then main/parent app has a navigation menu. One item, when clicked, creates an Iframe with SRC ATTRIBUTE loading App B inside.

When the user clicks into another option of the menu in app A, the Iframe is destroyed and another content View in React appears, replacing the Iframe.

When doing this, all data typed in forms by the user in B are gone, as I can not trigger a save event I have in B.

I have added following event handler in the iframe app:

window.addEventListener("beforeunload", function (e) {

    // Trigger here the save settigns event inside B
});

But former code is never triggering when user navigates through Main App menu. As I can see, navigating menu in App A, changes URL in the browser(but seems a SPA React.js routing or similar, no real redirection).

Question is: Can Iframe detect when is going to be unloaded/destroyed to trigger first the Saving Settings in Ajax ? P.S: I don't have access to App A code.

Thanks in advance


Solution

  • From MDN:

    The WindowEventHandlers.onbeforeunload event handler property contains the code executed when the beforeunload is sent. This event fires when a window is about to unload its resources. The document is still visible and the event is still cancelable.

    The unload event is fired when the document or a child resource is being unloaded. It is fired after:

    1. beforeunload (cancellable event)
    2. pagehide

    Example:

    <body>
        <input type="button" id="removeIframeBtn" value="remove iframe"/>
        <iframe id="iframe" src="http://localhost:8080/iframe.html"></iframe>
    </body>
    
    <script>
        const removeIframeBtn = document.getElementById("removeIframeBtn");
        const iframe = document.getElementById("iframe");
    
        iframe.contentWindow.onbeforeunload = function () {
            debugger;
        };
    
        window.onbeforeunload = function () {
            debugger;
        };
    
        removeIframeBtn.onclick = function () {
            iframe.remove();
        };
    </script>
    

    Let assume that page with current code is opened in the browser tab.

    If you try to close this tab, iframe.contentWindow.onbeforeunload will be called.

    If you try to click on remove iframe btn, iframe will be removed from document but iframe.contentWindow.onbeforeunload will not call. There is no unload event.

    React renders components with js, so it is totally like second case with clicking on remove iframe btn.

    So the answer on your question is: it is not possible to detect unloading of iframe with onbeforeunload event in single page application on route changing.

    Solution for you can be to save settings on every its change.