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:
- evt.preventDefault();
- evt.stopPropagation();
- throw 'something';
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...