You can view and download all files in the Samples in the Demo Kit at Routing and Navigation - Step 4.
<mvc:View
controllerName="sap.ui.demo.nav.controller.NotFound"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc">
<MessagePage
title="{i18n>NotFound}"
text="{i18n>NotFound.text}"
description="{i18n>NotFound.description}"
showNavButton="true"
navButtonPress="onNavBack"/>
</mvc:View>
In the NotFound
view, we set the property
showNavButton
of the MessagePage
control to
true
to automatically display the Back
button. We also add an event handler function onNavBack
to the
navButtonPress
event of the control. The
onNavBack
function will handle the actual back navigation. We
could directly add this function to the view's controller. However, we are smart
enough to anticipate that we might need the same handler function for different
views. DRY ("Don't Repeat Yourself") is the right approach for us, so let's
create a BaseController
from which all other controllers will
inherit.
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/routing/History",
"sap/ui/core/UIComponent"
], function(Controller, History, UIComponent) {
"use strict";
return Controller.extend("sap.ui.demo.nav.controller.BaseController", {
getRouter : function () {
return UIComponent.getRouterFor(this);
},
onNavBack: function () {
var oHistory, sPreviousHash;
oHistory = History.getInstance();
sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
window.history.go(-1);
} else {
this.getRouter().navTo("appHome", {}, true /*no history*/);
}
}
});
});
Create a new BaseController.js
file in the
webapp/controller
folder. The base controller implements a set
of functions that are reused by its subclasses. The onNavBack
handler is a great example of code that we don't want to duplicate in our
controllers for each page that has a back navigation.
The function checks if there is a previous hash value in the app history. If so, it
redirects to the previous hash via the browser's native History
API. In case there is no previous hash we simply use the router to navigate to the
route appHome
which is our home view.
The third parameter of navTo("appHome", {}, true /*no history*/);
has the value true
and makes sure that the hash is replaced. With
the line sap.ui.core.UIComponent.getRouterFor(this)
you can easily
access your component's router throughout the app. To make it even more comfortable,
we also add a handy shortcut getRouter
to the base controller. This
function is now available in each subclass as well. It is also used in the
onNavBack
handler to get a reference to the router before
calling navTo
. We now have to implement the reuse in all other
controllers.
In SAPUI5 there are
multiple options to reuse code. We recommend to use a base controller for such
helper methods because this allows us to decoratively use the
onNavBack
handler directly in any XML view without adding
additional code to the controller. Our base controller is an abstract controller
that will not be instantiated in any view. Therefore, the naming convention
*.controller.js
does not apply, and we can just call the
file BaseController.js
. By not using the naming convention
*.controller.js
we can even prevent any usage in views.
sap.ui.define([ "sap/ui/demo/nav/controller/BaseController" ], function (BaseController) { "use strict"; return BaseController.extend("sap.ui.demo.nav.controller.NotFound", { onInit: function () { } }); });
In order to reuse the base controller implementation, we have to change the
dependency from sap/ui/core/mvc/Controller
to
sap/ui/demo/nav/controller/BaseController
and directly extend
the base controller.
At this point you can open index.html#/thisIsInvalid
in your browser
and press the Back button to see what happens. You will be
redirected to the app's home page that is matched by the route
appHome
as you opened the Not Found page
with an invalid hash. If you change the hash to something invalid when you are on
the home page of the app, you will also go to the Not Found
page but with a history entry. When you press back, you will get to the home page
again, but this time with a native history navigation.
sap.ui.define([ "sap/ui/demo/nav/controller/BaseController" ], function (BaseController) { "use strict"; return BaseController.extend("sap.ui.demo.nav.controller.App", { onInit: function () { } }); });
To be consistent, we will now extend all of our controllers with the base controller. Change the app controller as described above.
sap.ui.define([ "sap/ui/demo/nav/controller/BaseController" ], function (BaseController) { "use strict"; return BaseController.extend("sap.ui.demo.nav.controller.Home", { }); });
The same applies to our home controller, we also extend it with the base controller now.
In this step we have added the Back button. The user can always use the browser's native Back button as well. Each app can freely configure the behavior of the Back button. However, there is no clean way to apply the same logic for the browser's Back button in single-page applications. Tweaking the browser history or using other quirks for cancelling backward or forward navigation is not recommended due to the implementation details of the browsers. The browser's Back button always uses the browser history while the Back button of the app can make use of the browser history or can implement its own navigation logic. Make sure to understand this difference and only control the Back button inside the app.
Implement a global onNavBack
handler for back navigation in
your app
Query the history and go to the home page if there is no history available for the current app