1

We have SAPUI5 Shell placed at a div inside an index.xhtml page. When user modifies the data in our application, user can perform 3 types of action for navigating away from the application:

  1. Press the cancel button in our application
  2. Type some other URL in the browser address bar
  3. Press the back-button in the browser bar.

Our SAPUI5/Openui5 application works with the route concept (sap.ui.core.routing.Router) and hence the application has 'HASH URL'.

For 1 & 2, we made the following change and it works (based on Mozilla recommendation)

window.onbeforeunload = function(e) {
  var dialogText = 'Dialog text here';
  e.returnValue = dialogText;
  return dialogText;
};

Mozilla Recommendation - https://developer.mozilla.org/en-US/docs/Web/API/WindowEventHandlers/onbeforeunload

But for pt.3 - when user presses BACK BUTTON, the HASH URL changes. Based on other discussion on Stackoverflow, playing around with browser history or disabling the browser back button is not working with Browser/Web World.

Is there a way to do the following when browser back button is pressed:

  1. Show Popup giving user an option to Stay or Leave (informing changes in page will be lost)
  2. If user chooses to stay, then the URL remains including the 'HASH URL' part.
Robin
  • 152
  • 3
  • 14

1 Answers1

1

One possible way you can achieve this is by disabling the dispatching of the changed event from the Hasher plugin and handle the hashchange event yourself to prompt user with a confirmation message. You would want to make sure this is only done while your user is on the edit view in question and then re-enable the standard logic once user either clicks cancel, saves or confirms to navigate away.

A rough example of this as follows...

onInit: function() {
  this._hashHandler = (function(){
    var sCurrentHash;

    var fnHandleHashChange =function(e){
        var sOldHash = e.oldURL.substr(e.oldURL.search("#")+1);
        var sNewHash = e.newURL.substr(e.newURL.search("#")+1);

        if(sCurrentHash!==sOldHash){
            return;
        }

        if(confirm("Are you sure you want to navigate away?")){
            window.removeEventListener("hashchange",fnHandleHashChange);
            window.hasher.setHash(sOldHash.substr(1));
            window.hasher.changed.active=true;
            window.hasher.setHash(sNewHash.substr(1));
        } else {
            window.hasher.setHash(sOldHash.substr(1));
        }
    }

    return {
        startManualHashChangeHandling: function() {
            sCurrentHash = window.location.hash.substr(1);
            window.hasher.changed.active=false;
            window.addEventListener("hashchange",fnHandleHashChange);
        },
        stopManualHashChangeHandling: function() {
            window.hasher.changed.active=true;
            window.removeEventListener("hashchange",fnHandleHashChange);
        }
    };
  }());
}

...so whenever you want to prevent user navigating without confirmation (so for example within a onEdit or onRouteMatched method) you can call...

this._hashHandler.startManualHashChangeHandling();

...and then to disable the manual hash change handling (for example in your onCancel or onSave success method)...

this._hashHandler.stopManualHashChangeHandling();
Ian MacGregor
  • 513
  • 1
  • 4
  • 11
  • Thanks Ian for the reply. Will try it out. There was a discussion that should this be a default behavior of OpenUI5 router to provide 'pre Hash Change Event' and stop propagation, rather every application to implement such a logic. Do you know if this exists by default with OpenUI5? – Robin Jan 16 '17 at 18:28
  • That would be nice, although I cannot see that it exists in the current version. There is the hashChanged event of the HashChanger - https://sapui5.hana.ondemand.com/#docs/api/symbols/sap.ui.core.routing.HashChanger.html#event:hashChanged - however this won't prevent propagation as the standard hashChanged event is called first. – Ian MacGregor Jan 16 '17 at 20:12