4

I have an angular application which is kind of the main application that hosts sub application inside it. The sub applications are also angular applications. The way that I load sub application is through Iframes.

The sub-applications are shown as a list and when I click on an tab, that application is loaded. When I am making some changes to the data in an application and if I click on another sub-tab, I wanted to show a warning message saying " changes will be lost". I am able to achieve it by using beforeunload event as below. I can check to see if there are any unsaved changes and show the warning popup.

  @HostListener('window:beforeunload', ['$event'])
  unloadNotification($event: any) {
      if (**my logic here) {
          $event.returnValue =true;
      }
  }

The only problem with this is, when I click the other sub-tab, the host application highlights that sub-tab and then the warning pop-up is shown. If I click on stay button on the popup, I am able to be on the sub-tab I want but on the host application the other sub-tab is highlighted. So I am trying to see a way to not highlight the other tab if I want to stay on the current sub-tab. Something before beforeunload.

indra257
  • 66
  • 3
  • 24
  • 50

4 Answers4

5

My understanding is you have to update an existing project that's been constructed in such a way that the beforeunload event is employed to achieve something similar to the Angular feature called route guards. You do or don't load the selected iframe depending on your logic implemented with the help of beforeunload event. You don't seem to favor changing this implementation that's why seeking a solution that covers your requirement applying a similar approach like another window event.

If my understanding is correct, you need to refactor this implementation so that the "guarding" happens depending on the inner workings of the "host application" where it actually has to be in the first place. The issue you have arises because by the time the iframe's unload event is canceled, host application's canceled tab gets already selected.

In short, this seems to be handled in your tab's selection event. My answer may or may not propose a solution you would accept, since we don't have all the details like which component suit you use, I can only present a pseudo solution:

Inside the component where your navigation tab's ui logic takes place:

onTabSelected(selectedIndex) {
    if (..your logic here) {
        loadIframe(selectedIndex);
        highlightTab(selectedIndex);
    }
}
talhature
  • 2,246
  • 1
  • 14
  • 28
4

There is no such event as before beforeUnload. Two applications i.e. host and child can communicate via postMessage. so in beforeUnload event you can send a postMessage to child application to highlight existing tab. for eg:- let say you had reference of child window in variable name child1.

  child1.postMessage('{'tabId': 'tab1'}');

Your child application can receive this message and highlight the tab with identifier tab1.

Aakash Garg
  • 10,649
  • 2
  • 7
  • 25
1

Maybe we can create a communication system using the window.top object for example let's say that in the child apps you assign some id.

Then in the main app which hosts the others you create a subobject to window.top.appsMap = {};

Then from each child app you update a boolan value for example

window.top.appsMap['applicationId'] = hasChangesOrNot

Then from the top app where you change tabs you can check if the current opened tab app id has changes and not switch the tab but just try to unload the current iframe, it's not the best solution but if should work you can maybe also set some communication channel backwards which would trigger from the main app which hosts the others the save from the child app

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Nicu
  • 3,476
  • 4
  • 23
  • 43
-1

In child app

const origin = this.getCurrentHostOrigin();
if (cancelSwitchTab) {
    window.parent.postMessage({}, origin); 
}

In host app:

this.renderer.listen(this.windowsRef.nativeWindow, 'message', event => {
  const message = event.data;
  *** your logic to revert highlight to current tab ***
});
Vincent
  • 1,178
  • 1
  • 12
  • 25
  • How do we know whether the user has clicked stay or leave on the unsaved changed dialog? – indra257 Jun 15 '20 at 14:42
  • @indra257 can you clarify from the original question that what is "highlight" meaning and how is it different from "be on the sub-tab". This is quite confusing: "I am able to be on the sub-tab I want but on the host application the other sub-tab is highlighted." (Q: if you are able on the sub-tab you want why you also say the other is highlighted?) And how did you check if it needs to show a popup? and who did the popup (host or child)? – Vincent Jun 15 '20 at 19:52
  • @vincet-cm the host app, has a tab list of child apps. If I am on tab2 and have some un saved changes, if click on tab1, I wanted to show the unsaved changes warning in tab2. I have a property to check if there are un saved changes. So when I click on tab1, I am able to go to the beforeunload event and check for the property to see if there are any unsaved changes. But as the tab1 is already clicked, the host application highlights the tab that is clicked. So it highlights that tab. – indra257 Jun 15 '20 at 21:47
  • Even if I click on "stay" on the tab2's unsaved changes, I will remain on the tab2 but tab1 is still highlighted in the host app. So I need to find a way in the child app/tab2 to see if the user clicked on the "stay" button on the un saved changes dialog so that I can send a message to the host application to de-select tab1 – indra257 Jun 15 '20 at 21:48
  • @indra257 if the popup is provided by the child app then why you cannot directly send the status (stay) from that child app to host? – Vincent Jun 15 '20 at 23:08