Routing and Navigation
Routing and Navigation
Objectives
Routing Overview
SAPUI5 offers hash-based navigation, which allows you to build single-page apps
where the navigation is done by changing the hash. In this way, the browser does not
have to reload the page.
Hash-based navigation enables bookmarks and deep links to pages inside an app; this
means that you can start the app and resume the bookmarked state.
Routing Configuration
In the application descriptor, the routing configuration is found in the routing property of
the sap.ui5 namespace. It consists of the following three sections: config, routes,
and targets.
In the following exercises, the scenario is extended by a navigation option: When the
user selects a customer in the customer table, a new view with details about the
selected customer is to be displayed.
To be able to implement this navigation, you have to adapt the structure of the
application: Until now, the component has used the App view as root view, which in turn
contains an App UI element in whose pages aggregation the Overview is statically
embedded. For navigation, however, the embedding of views in the pages aggregation
must be done dynamically. The navigation is implemented in such a way that the views
are exchanged in the pages aggregation through the router.
In this exercise, you will first restructure the application so that the Overview view is no
longer statically embedded in the pages aggregation of the App UI element, but
dynamically via routing configuration. In the following exercises, you will then implement
the actual navigation on this basis.
Task 1: Remove the Overview View from the pages Aggregation of the App UI
Element
Steps
1. Open the App.view.xml file from the webapp/view folder in the editor.
2. Delete the following lines in the implementation of the view to remove the static
embedding of the Overview view in the pages aggregation of the App UI element:
Code snippet
Copy code
1 <pages>
2 <mvc:XMLView
viewName="sap.training.exc.view.Overview"/>
3 </pages>
Result
3. Add the id="app" attribute to the <App> tag to set an Id for the App UI element.
Note
The Id will be used later in the routing configuration to specify the App UI element
as the parent to insert views.
Result
Steps
1. Open the manifest.json application descriptor from the webapp folder in the
editor.
2. In the application descriptor, look for the routing property in
the sap.ui5 namespace:
Code snippet
Copy code
1 "routing": {
2 "config": {
3 "routerClass": "sap.m.routing.Router",
4 "viewType": "XML",
5 "async": true,
6 "viewPath": "sap.training.exc.view",
7 "controlAggregation": "pages",
8 "controlId": "<...>"
9 },
10 "routes": [],
11 "targets": {}
12 }
Copy code
Note
The three properties config, routes, and targets in the routing section define
the routing and navigation structure of the application.
3. Replace the "<...>" value of the controlId property with "app", which is the Id
assigned above for the App UI element.
Note
Result
Code snippet
Copy code
1 {
2 "name": "overview",
3 "pattern": "",
4 "target": [
5 "overview"
6 ]
7 }
Note
This defines a route called overview, for which the target named overview is
displayed when the hash of the browser is empty. The
referenced overview target is defined in the next step.
Result
Code snippet
Copy code
1 "overview": {
2 "viewId": "overview",
3 "viewName": "Overview",
4 "viewLevel": 1
5 }
Note
This defines that the overview target referenced above will be used to load the
Overview view.
Result
Steps
1. Open the Component.js file from the webapp folder in the editor.
2. Add the following code to the end of the init method of the component
controller:
Code snippet
Copy code
1 this.getRouter().initialize();
Note
The routing configuration done above causes the router to load the Overview
view into the pages aggregation of the App UI element when the hash of the
browser is empty. To enable this configuration for the application, the router is
initialized here.
Result
The initialization method of the component controller should now look like this:
3. Test run your application by starting it from the SAP Business Application Studio.
Caution
Use the start-mock npm script to start the application.
Make sure that the application works unchanged from the user's point of view:
The Overview view is displayed in the browser. However, unlike the previous
implementation, the Overview view is now embedded in the pages aggregation of
the App UI element via routing.
a. Right-click on any subfolder in your sapui5-development-learning-
journey project and select Preview Application from the context menu that
appears.
b. Select the npm script named start-mock in the dialog that appears.
c. In the opened application, check if the component works as expected.
In the example shown, a route named detail is defined for which the target
named detail is displayed, which in turn is used to load a view named Detail.
To define the route, the hard-coded pattern detail is used. This pattern only matches if
the hash of the browser is detail and no data is passed on to the events of the route.
In the example shown, the navTo method of the router is used in an event handler
method of a view controller to navigate to the route named detail. This sets the
pattern detail of the detail route (see above) to the browser's hash. SAPUI5 then
reacts to the browser's hashchange event to find the route that matches that hash. This
results in the target of the detail route - in the end, the Detail view - being displayed in
the browser.
After you have set up the routing for the application in the last exercise, you will now
implement a basic navigation based on this.
The ultimate goal is to implement the following scenario: When the user selects an entry
in the customer table, they are to be navigated to a view called Detail, which is used to
display additional information about the selected customer.
As a first step for the implementation of this scenario, you will set up the basic
navigation from the Overview view to the Detail view in this exercise. No customer data
will be displayed on the Detail view yet.
Note
For simplicity, the project already contains the
files Detail.view.xml and Detail.controller.js needed for the implementation of
the Detail view. However, there are no UI elements on the view yet and the controller
implementation is also still empty. For this exercise, only a Page UI element with a translatable
title is needed on the Detail view. You will implement this in the next steps.
Steps
1. Open the i18n.properties resource bundle file from the i18n folder in the editor.
Code snippet
Copy code
1 detailPageTitle=Customer Details
Result
The i18n.properties resource bundle file should now look like this:
3. Now open the Detail.view.xml file from the webapp/view folder in the editor.
4. Add the following code to the view to display a (still empty) page with the title
created above:
Code snippet
Copy code
1 <Page title="{i18n>detailPageTitle}">
2 <content>
3
4 </content>
5 </Page>
Result
Steps
1. Open the manifest.json application descriptor from the webapp folder in the
editor.
Code snippet
Copy code
1 "routing": {
2 "config": {
3 "routerClass": "sap.m.routing.Router",
4 "viewType": "XML",
5 "async": true,
6 "viewPath": "sap.training.exc.view",
7 "controlAggregation": "pages",
8 "controlId": "app"
9 },
10 "routes": [
11 {
12 "name": "overview",
13 "pattern": "",
14 "target": [
15 "overview"
16 ]
17 }
18 ],
19 "targets": {
20 "overview": {
21 "viewId": "overview",
22 "viewName": "Overview",
23 "viewLevel": 1
24 }
25 }
26 }
Copy code
3. Add the following object to the routes array to define a route called detail, for
which the target named detail is displayed when the hash of the browser
equals detail:
Code snippet
Copy code
1 {
2 "name": "detail",
3 "pattern": "detail",
4 "target": [
5 "detail"
6 ]
7 }
Note
Result
Code snippet
Copy code
1 "detail": {
2 "viewId": "detail",
3 "viewName": "Detail",
4 "viewLevel": 2
5 }
Result
The routing configuration done above causes the router to load the Detail view into
the pages aggregation of the App UI element when the hash of the browser
equals detail. Therefore, in the following steps, you will set the browser's hash to this
value via the navTo method of the router when the user selects a customer from the
customer table.
Steps
1. Open the Overview.view.xml file from the webapp/view folder in the editor.
2. Add the following two attributes to the <ColumnListItem> tag in the customer
table:
Code snippet
Copy code
1 type="Navigation" press=".onNavToDetails"
Note
The Navigation type indicates that the table rows are navigable to display additional
information. When selecting a row, the onNavToDetails event handler method is
called, which is implemented in the next step and in which the navigation is triggered.
Result
4. Add the onNavToDetails event handler method to the view controller as follows to
trigger navigation to the Detail view:
Code snippet
Copy code
1 onNavToDetails: function () {
2 var oRouter = this.getOwnerComponent().getRouter();
3 oRouter.navTo("detail");
4 }
Note
The view controller should now have the following additional method:
5. Test run your application by starting it from the SAP Business Application Studio.
Caution
Use the start-mock npm script to start the application.
Make sure that the Detail view is displayed when a customer is selected in the customer
table.
Note
Please keep in mind that the navigation from the Detail view back to the Overview view
is not supported yet. This will be implemented in the next exercise.
b. Select the npm script named start-mock in the dialog that appears.
Objectives
Back Navigation
To navigate back in an application, the user can use the browser's native Back button.
However, this Back button always uses the browser history for navigating back. This
means that if you start the application with a certain hash value in the browser and then
press the Back button, the application is exited via this button.
To change this behavior, a separate Back button is implemented for the application in
the example shown. In the implementation of the corresponding onNavBack event
handler method, the sap/ui/core/routing/History module is used to access the
navigation history of the SAPUI5 application. The getPreviousHash method of the
history object is employed to check if there is a previous hash value in the app history. If
so, the application navigates to this previous hash via the browser's native history API.
In this case, the functionality of the app's Back button matches the functionality of the
native browser Back button.
The second parameter when calling the navTo method is an empty object as no
additional parameters are passed to the route. The third parameter has the
value true and makes sure that the hash is replaced, so that there will be no entry in
the browser history.
In the last exercise, you implemented the navigation from the Overview view to the
Detail view. In this exercise, you will set up the corresponding back navigation: from the
Detail view to the Overview view.
Steps
1. Open the Detail.view.xml file from the webapp/view folder in the editor.
2. Add the following two attributes to the <Page> tag to display a back button and
register an event handler that is called when the back button is pressed:
Code snippet
Copy code
1 showNavButton="true" navButtonPress=".onNavBack"
Note
The onNavBack event handler method will be implemented in the following steps.
Result
Steps
Result
Code snippet
Copy code
1 onNavBack: function () {
2 var oHistory = History.getInstance();
3 var sPreviousHash = oHistory.getPreviousHash();
4
5 if (sPreviousHash !== undefined) {
6 window.history.go(-1);
7 } else {
8 var oRouter = this.getOwnerComponent().getRouter();
9 oRouter.navTo("overview", {}, true);
10 }
11 }
Copy code
Note
In the implementation of the event handler, the browser history is used to return to the
previous page if a navigation step has already taken place in the application. If no
navigation has yet taken place within the application, the router is used to navigate to the
Overview view. That is, even if the application was started directly by calling the Detail
view, the back button leads to the Overview view and not to a page outside the
application.
Result
4. Test run your application by starting it from the SAP Business Application Studio.
Caution
Use the start-mock npm script to start the application.
Make sure that it is now possible to navigate back from the Detail view to the Overview
view.
b. Select the npm script named start-mock in the dialog that appears.
Objectives
Display a notification view if a hash is entered for which there is no matching route
Invalid Hashes
If a user tries to access an invalid pattern that does not match any of the configured
routes, they should be notified that something went wrong.
The notFound target is configured in the targets section. It loads the XML
view sap.training.exc.view.NotFound without animation (show transition) into
the pages aggregation of the UI control with the app Id.
Note
To display routing related error messages on a view, you can use
the sap.m.MessagePage control.
In the previous exercises, you configured two routes. Using the configuration you made,
the Overview view is displayed if the hash of the browser is empty. In addition, if the
hash of the browser equals detail, the Detail view is displayed.
In this exercise, you will implement a view called NotFound, which is to be displayed via
appropriate configuration if a hash is entered for which there is no matching route. The
NotFound view should display an error message and a link that allows the user to
navigate from the NotFound view to the Overview view.
Git Repository: https://github.com/SAP-samples/sapui5-development-learning-
Template:
journey.git, Branch: sol/24_back_navigation
Note
In this task of the exercise, you will add a MessagePage UI element to the NotFound view
with a translatable title and a translatable error message. You will implement this in the
next steps.
In the last task of this exercise, you will also add a link to the NotFound view that allows
the user to navigate to the Overview view.
Steps
1. Open the i18n.properties resource bundle file from the i18n folder in the editor.
Code snippet
Copy code
1 notFoundPageTitle=Not Found
2 notFoundPageText=Sorry, but the requested resource is
not available.
Result
The i18n.properties resource bundle file should now look like this:
3. Open the NotFound.view.xml file from the webapp/view folder in the editor.
4. Add the following code to the view to display a message page with the title and
the text created above:
Code snippet
Copy code
1 <MessagePage
2 title="{i18n>notFoundPageTitle}"
3 text="{i18n>notFoundPageText}">
4
5 </MessagePage>
Result
Steps
1. Open the manifest.json application descriptor from the webapp folder in the
editor.
Code snippet
Copy code
1 "routing": {
2 "config": {
3 "routerClass": "sap.m.routing.Router",
4 "viewType": "XML",
5 "async": true,
6 "viewPath": "sap.training.exc.view",
7 "controlAggregation": "pages",
8 "controlId": "app"
9 },
10 "routes": [
11 {
12 "name": "overview",
13 "pattern": "",
14 "target": [
15 "overview"
16 ]
17 },
18 {
19 "name": "detail",
20 "pattern": "detail",
21 "target": [
22 "detail"
23 ]
24 }
25 ],
26 "targets": {
27 "overview": {
28 "viewId": "overview",
29 "viewName": "Overview",
30 "viewLevel": 1
31 },
32 "detail": {
33 "viewId": "detail",
34 "viewName": "Detail",
35 "viewLevel": 2
36 }
37 }
38 }
Copy code
3. Add the following property to the config section to specify the navigation target
that is used whenever no navigation pattern is matched:
Code snippet
Copy code
1 "bypassed": {
2 "target": [
3 "notFound"
4 ]
5 }
Note
Result
Code snippet
Copy code
1 "notFound": {
2 "viewId": "notFound",
3 "viewName": "NotFound",
4 "transition": "show"
5 }
Result
Steps
1. Add the following key-value pair to the i18n.properties resource bundle file:
Code snippet
Copy code
Note
The key-value pair provides the translatable text for the link on the NotFound view that
you will create in the next step. This link will allow the user to navigate from the
NotFound view to the Overview view.
Result
The i18n.properties resource bundle file should now look like this:
2. Now add the customDescription aggregation to the <MessagePage> tag on the
NotFound view as follows to display a link with the text created above on the
page:
Code snippet
Copy code
1 <customDescription>
2 <Link text="{i18n>navToOverviewLinkText}"
press=".onNavToOverview"/>
3 </customDescription>
Note
The onNavToOverview event handler registered here for pressing the link will be
implemented in the next step.
Result
Code snippet
Copy code
1 onNavToOverview: function () {
2 var oRouter = this.getOwnerComponent().getRouter();
3 oRouter.navTo("overview", {}, true);
4 }
Result
Caution
Use the start-mock npm script to start the application.
Make sure that the NotFound view is displayed if a hash is entered for which there is no
matching route (for example, foo). Also make sure that the user can navigate from the
NotFound view to the Overview view via the link displayed there.
b. Select the npm script named start-mock in the dialog that appears.
Objectives
SAPUI5 supports routes with mandatory and optional parameters, which are both
defined in the pattern of a route. You specify a mandatory parameter for the pattern by
placing the parameter in curly brackets.
In the example shown, a mandatory parameter named customerId is defined for
the detail route. This makes, for example, the
hashes detail/5 and detail/(00505604-4e85-1edd-818f-21e64b9cd2cf) match the
route, while the hash detail/ does not. The patternMatched event of the route (see the
next section) is then passed 5 or (00505604-4e85-1edd-818f-21e64b9cd2cf)
as customerId in its arguments parameter.
Parameter Handling
The parameters of a route are set using the navTo method of the router. After the name
of the route to be navigated to, a configuration object with the parameter values for the
route is passed to this method as the second parameter.
The router always makes sure that mandatory parameters as specified in the route's
pattern are set; otherwise an error is thrown.
Let's look at an example for setting parameter values and receiving parameter values,
respectively.
In the previous exercises, you added navigation from the Overview view to the Detail
view to the scenario. So far, however, no customer-specific data is displayed on the
Detail view. This will be implemented in this exercise: Additional data for the customer
selected on the Overview view is to be displayed on the Detail view.
To do this, you will first add fields for customer-specific data to the UI of the Detail view.
Then you will add a mandatory parameter to the detail route and use it to pass the Id
of the customer selected on the Overview view to the Detail view during navigation.
Finally, you will use the passed Id in the detail view controller to set the binding context
for the Detail view. This allows the relative binding paths used on the view to be
resolved and the corresponding customer data to be displayed on the view.
Steps
1. Open the i18n.properties resource bundle file from the i18n folder in the editor.
Code snippet
Copy code
1 customerNumberTitle=Customer Number
2 streetTitle=Street
3 postcodeTitle=Post Code
4 cityTitle=City
5 countryTitle=Country
6 emailTitle=Email
7 phoneTitle=Telephone
8 discountTitle=Discount
Copy code
Result
The i18n.properties resource bundle file should now look like this:
3. Open the Detail.view.xml file from the webapp/view folder in the editor.
4. Add the following object header to the content aggregation of the Page UI
element to display fields with customer specific data on the view:
Code snippet
Copy code
1 <ObjectHeader
2 responsive="true"
3 fullScreenOptimized="true"
4 title="{Form} {CustomerName}">
5 <attributes>
6 <ObjectAttribute title="{i18n>customerNumberTitle}"
text="{CustomerNumber}"/>
7 <ObjectAttribute title="{i18n>streetTitle}"
text="{Street}"/>
8 <ObjectAttribute title="{i18n>postcodeTitle}"
text="{PostCode}"/>
9 <ObjectAttribute title="{i18n>cityTitle}"
text="{City}"/>
10 <ObjectAttribute title="{i18n>countryTitle}"
text="{Country}"/>
11 <ObjectAttribute title="{i18n>emailTitle}"
text="{Email}"/>
12 <ObjectAttribute title="{i18n>phoneTitle}"
text="{Telephone}"/>
13 <ObjectAttribute title="{i18n>discountTitle}"
text="{ path: 'Discount',
14
type: 'sap.ui.model.type.Float',
15
formatOptions: {minFractionDigits: 2, maxFractionDigits: 2}
16
} %"/>
17 </attributes>
18 </ObjectHeader>
Copy code
Note
Relative paths are used here for binding the customer fields. As long as the context for
this binding is not set, these paths cannot be resolved and hence no data can be
displayed. In the next steps, you will therefore provide the corresponding binding
context.
Result
Task 2: Pass the Id of the Customer Selected on the Overview View to the
Detail View via a Mandatory Parameter of the detail Route
Steps
1. Open the manifest.json application descriptor from the webapp folder in the
editor.
2. In the application descriptor, find the routes property in the routing configuration
section of the sap.ui5 namespace:
Code snippet
Copy code
1 "routes": [
2 {
3 "name": "overview",
4 "pattern": "",
5 "target": [
6 "overview"
7 ]
8 },
9 {
10 "name": "detail",
11 "pattern": "detail",
12 "target": [
13 "detail"
14 ]
15 }
16 ]
Copy code
3. Change the value of the pattern property in the detail route to the following new
value:
Code snippet
Copy code
1 "pattern": "detail/{customerId}"
Note
With this, you add a mandatory parameter called customerId to the detail route. This
parameter is used in the next step to pass the Id of the customer selected in the
customer table on the Overview view to the Detail view.
Result
Code snippet
Copy code
1 onNavToDetails: function (oEvent) {
2 var oItem = oEvent.getSource();
3 var oRouter = this.getOwnerComponent().getRouter();
4
5
6 oRouter.navTo("detail", {
7 customerId:
oItem.getBindingContext().getPath().substring("/UX_Customer"
.length)
8 });
9 }
Copy code
Note
Result
The onNavToDetails event handler method should now look like this:
Task 3: Use the Customer Id Passed via Routing in the Detail View Controller
to Set the Binding Context for the Detail View
Steps
Code snippet
Copy code
1 onInit: function () {
2 var oRouter = this.getOwnerComponent().getRouter();
3
oRouter.getRoute("detail").attachPatternMatched(this._onObje
ctMatched, this);
4 }
Note
Result
3. Implement the _onObjectMatched method as follows to set the context for the
bindings on the Detail view:
Code snippet
Copy code
1 _onObjectMatched: function (oEvent) {
2 this.getView().bindElement("/UX_Customer" +
oEvent.getParameter("arguments").customerId);
3 }
Note
Result
4. Test run your application by starting it from the SAP Business Application Studio.
Caution
Use the start-mock npm script to start the application.
Make sure that the Detail view now displays data of the customer selected in the table
on the Overview view.
b. Select the npm script named start-mock in the dialog that appears.