In my SAPUI5 application I'm using a sap.tnt.Toolpage as the main layout container. The SideNavigation shows a list of application links and the mainContents is dynamically loaded using the sap.ui.core.routing.Router.
To navigate to a detail page I'm using
var router = sap.ui.core.UIComponent.getRouterFor(this);
router.navTo("MyDetailRoute", {
detailItemId: oItem.getBindingContext("oDataSourceName").getProperty("DETAILID")
});
This loads a detail view which then binds it's controls to the data from my data source.
The problem arises when I try to remember the user to save his changes back to the server. I basically want to interrup the navigation to aks the user if he'd like to a) Cancel his changes, b) Save his changes or c) Stay on the detail page. While a) and b) are easy to implement, I don't know how to prevent the navigation from happening.
I've tried so far by subscribing to onBeforeHide of my view:
var view = this.getView();
var that = this;
view.addEventDelegate({
onBeforeHide: function (evt) {
var oModel = that.getModel("oDataSourceName");
if (oModel.hasPendingChanges()) {
// How to prevent leaving the page?
}
}
});
Things I've tried that are not working:
Option 3) actually prevents the navigation but leads to later problems because the URL will change nevertheless...
Does anyone have an idea?
Edit: Thanks to the answer from cschuff I was able to get it working. For anyone who has the same problem in the future:
// In onInit: Subscribe to onBeforeHide in order to un-register event handler for hashchange
onInit: function () {
this.getRouter().getRoute("MyDetailRoute").attachPatternMatched(this.onNavigated, this);
var view = this.getView();
var that = this;
view.addEventDelegate({
onBeforeHide: function (evt) {
$(window).off('hashchange');
}
});
}
// Then in onNavigate stoppen the router, saving the current window location and subscribing to hashchange (only once)
// In hashchange use helper variable m_bSelfURLSetting to prevent the function from running when triggered by URL restore (above)
// In the handler checking for pending changes and either resore the old URL or starting the router again if the user wants to quit or if there are no changes
onNavigated: function (oEvent) {
this.getRouter().stop();
this.m_strHref = window.location.href;
var that = this;
$(window).off('hashchange').on('hashchange', function (e) {
if (that.m_bSelfURLSetting) {
that.m_bSelfURLSetting = false;
return;
}
var oModel = that.getModel("oDataSourceName");
if (oModel.hasPendingChanges()) {
var leave = confirm('There are unsaved changes.\r\n\r\nDo you really want to leave the page?');
if (!leave) {
// re-set the URL
that.m_bSelfURLSetting = true;
window.location.href = that.m_strHref;
}
else {
that.getRouter().initialize(false);
oModel.resetChanges();
}
} else {
that.getRouter().initialize(false);
}
});
}
This is definitively not the kind of code one is proud of...
To prevent a webpage from navigating away using JavaScript, we can set the window. onbeforeunload property to a function that returns any value. window. onbeforeunload = () => { return ""; };
The onbeforeunload event occurs when the document is about to be unloaded. This event allows you to display a message in a confirmation dialog box to inform the user whether he/she wants to stay or leave the current page. The default message that appears in the confirmation box, is different in different browsers.
Solution #1: You could temporarily deactivate routing completely by using the Router methods stop
and initialize
. This will stop listening to changes in the url hash and thereby ignore all routing triggers.
From your controller:
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
oRouter.stop();
// later
// passing true will interpret and navigate to the current hash (since 1.48.0)
oRouter.initialize(true);
Solution #2: Interrupt routing itself using sap.ui.core.routing.HashChanger
events. hashChanged
and hashReplaced
are internally used by Router. You could also try if sap.ui.core.routing.Router
routeMatched
or beforeRouteMatched
are cancelable (Docs are not giving any hint).
Solution #3: A less restrictive solution would be to just interrupt all actions that trigger routing from that particular view. Be aware that browser-back or changing the url-hash manually will still work here (the native JS events beforeunload
and hashchange
might help here).
BR Chris
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With