SAPUI5 Routing and Navigation with Parameter – Part 9 – sapui5 tutorial for beginners

SAPUI5 provides routing class that not only facilitates routing and navigation but also helps to load the required pages when the app is loaded. In all our previous examples we defined page directly in the app so that it is loaded when the app gets loaded. Going forward, we make use of routing class to load page as well as to perform navigation in the app.

We implement the routing configuration in the app descriptor file i.e the manifest.json file. You must have separate view for each page of the app and we configure navigation between them.

This application is build from scratch. If you have been following our previous steps, you will find that there is a significant structural change in the application. The structure that our app will acquire now will be the structure that you should follow in real-world applications.

Our application will have the following structure.

SAPUI5 Routing and Navigation Example
SAPUI5 Routing and Navigation Example

If you compare with our previous example, we have added two views master and detail view, along with its controller. The App.view.xml file is still there, but the code inside it is transferred to Master.view.xml. Now the App.view.xml just holds the Shell and App control with id=”app”. Later in the post you will see that we do a configuration of property controlId:”app” in the Mainfiest.json file under section “config”. Now the router identifies the app control with this app ID and loads it. Next, the view needs to be loaded into the app control. The router automatically identifies the view to be loaded based on the current URL which is driven by the configuration done under “routes” and “targets” section in the Manifest.json file.

<mvc:View 
    controllerName="Amarmn.MyListApp.controller.App" 
    xmlns="sap.m" 
    xmlns:mvc="sap.ui.core.mvc"
    displayBlock="true">
	<Shell id="myShell">
		<App id="app"/>
	</Shell>
</mvc:View>

Since, we have discussed so much about the Manifest.json file, let’s complete code of Manifest file. The section that needs to be added is the “routing” section under the “sap.ui5” section of the app descriptor file. The “routing” section will have three subsections “config”, “routes” and “targets”.

The “config” section holds the global router configuration and default values that gets applied to “routes” and “targets” sections. Notice the “controlId”: “app” which is defined the in “config” section and about which we had explained earlier.

Understand the “routes” section. For “name”: “master”, the “pattern” is “” and the “target” is “master”. “pattern” empty will ensure that router loads “master” in to the app control first and displays it. The detail of name “master” is then defined in below “targets” section and mentions the viewId and viewName that will get loaded. So, “master” will load the master.view.

Once will click on the list in Master.view, the pattern configured for “name”: “detail” will get realized and router will load the detail view. Hence, it will be like navigation from master to detail view on the click on the list. Yes, this is the only configuration required in Manifest.json file.

"sap.ui5": {
	"rootView": {
		"viewName": "Amarmn.MyListApp.view.App",
		"type": "XML",
		"async": true,
		"id": "app"
	},
	...
"routing": {
	"config": {
		"routerClass": "sap.m.routing.Router",
		"viewType": "XML",
		"viewPath": "Amarmn.MyListApp.view",
		"controlId": "app",
		"controlAggregation": "pages",
		"async": true
	},
	"routes": [{
		"pattern": "",
		"name": "master",
		"target": "master"
	}, {
		"pattern": "detail/{productPath}",
		"name": "detail",
		"target": "detail"
	}],
	"targets": {
		"master": {
			"viewId": "master",
			"viewName": "Master"
		},
		"detail": {
			"viewId": "detail",
			"viewName": "Detail"
		}
	}
	},
	...
}

For the routing configuration to work, we just need to initialize it in the Component.js file.

sap.ui.define([
	"sap/ui/core/UIComponent"
], function (UIComponent) {
	"use strict";

return UIComponent.extend("Amarmn.MyListApp.Component", {

metadata : {
	manifest: "json"
	},
init : function () {
	// call the init function of the parent
	UIComponent.prototype.init.apply(this, arguments);
	// set data model
	// create the views based on the url/hash
	this.getRouter().initialize();
	}
});

});

Next, we move to the code of our Views.

The Master.view.xml is responsible to display the list. The only extra code, compared to previous example, is line no. 23 and 24 i.e type=”Navigation” and press=”.onPress”.

<mvc:View 
xmlns:core="sap.ui.core" 
xmlns:mvc="sap.ui.core.mvc" 
xmlns="sap.m" 
controllerName="Amarmn.MyListApp.controller.Master"
xmlns:html="http://www.w3.org/1999/xhtml">
<Page id="masterView" title="{i18n>masterPageTitle}">
<content>
<List 
id="ProductList" 
headerText="{i18n>ListTitle}" 
class="sapUiResponsiveMargin" 
width="auto" 
items="{product>/Products}">
<items>
<ObjectListItem 
id="ObjectList" 
title="{product>Quantity} x {product>ProductName}" 
number="{path: 'product>ExtendedPrice'}"
numberUnit="Dollars" 
numberState="{path: 'product>ExtendedPrice', 
         formatter: '.formatter.numberState'}" 
type="Navigation" 
press=".onPress">
<firstStatus>
<ObjectStatus id="statustext"
text="{ parts: [ 'product>ShipperName', 
                 'product>ShippedDate', 
                 'product>Status' ], 
    formatter: '.formatter.statusText' }"/>
</firstStatus>
</ObjectListItem>
</items>
</List>
</content>
</Page>
</mvc:View>

Let’s jump to Master.controller.js file and code the onPress function.

The getSource() method will give us the control instance that has been interacted with. We get the OjbectListItem has has been clicked. We pass this information to the detail page so that the detail page can display additional information based on this data.

sap.ui.core.UIComponent.getRouterFor(this) is helper method to access the router instance of our app. On the router we call the navTo method to navigate to the detail route that is already specified in the routing configuration.

Routing is not the only thing happening inside the onPress function. Apart from navigation from master to detail view, we also want to pass the data of the item which the user has selected. We can pass this information to the navigation parameter productPath which he had already defined in the detail route. A point to note is mandatory navigation parameters is defined with curly brackets and our productPath is defined under curly brackets. So, it is a mandatory parameter.

If you check the value of oItem.getBindingContext(“product”).getPath() in console, you will find that it holds / at the beginning and in between. / cannot be passed in parameter hence we have to remove it. Line no. 13 and 18 attempts to do the same.

sap.ui.define([
"sap/ui/core/mvc/Controller",
"../model/formatter",
"sap/ui/core/UIComponent"
], function (Controller, formatter, UIComponent) {
"use strict";

return Controller.extend(
  "Amarmn.MyListApp.controller.Master", {
formatter: formatter,
onPress: function (oEvent) {
var oItem = oEvent.getSource();
var oRouter = UIComponent.getRouterFor(this);
var itemclicked = 
  oItem.getBindingContext("product").getPath().substr(1);
//the path adds "/" at the beginning and in the middle
//we need to remove this to pass it as parameter
//the slashes will be placed back and X removed again 
//to create path in Detail.controller.js file
itemclicked = itemclicked.replace("/", "X");
oRouter.navTo("detail", {
productPath: itemclicked
});
}
});
});

onPress takes care of navigation and passing of parameter value to Detail.controller.js file.

In the Detail.controller.js file we need to set the context that we passed in with the URL parameter productPath on the view.

In the init method , first we fetch the instance of our app router. Next, we attach it to the detail route by calling the method attachPatternMatched. We register an internal callback function _onObjectMatched. This method will be executed when the route is hit, either by clicking on the item or by calling the app with a URL for the detail page. Here we receive an event that we can use to access the URL and navigation parameters.

Next we try to perform bindElement function on the view to set the context. The oEvent.getParameter(“arguments”) gets navigation parameter and we replace the “/” back at its places. We fulfill the bindElement function by providing the path and the model. All the UI controls placed inside the detail view will now get updated. Because of this bindElement we now have the ability to show additional information for the selected item on the detail page.

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(
"Amarmn.MyListApp.controller.Detail", {

onInit: function () {
var oRouter = UIComponent.getRouterFor(this);
oRouter.getRoute("detail")
.attachPatternMatched(this._onObjectMatched, this);
},

_onObjectMatched: function (oEvent) {
this.getView().bindElement({
path: "/" + oEvent.getParameter("arguments")
.productPath.replace("X", "/"),
model: "product"
});
},

onNavPress: function () {
var oHistory = History.getInstance();
var sPreviousHash = oHistory.getPreviousHash();
if (sPreviousHash !== undefined) {
		window.history.go(-1);
} else {
var oRouter = UIComponent.getRouterFor(this);
oRouter.navTo("master", {}, true);
}
}
});
});

And what does onNavPress function do? The code here takes care of navigation back from detail to master page. The onNavPress is event handler for navButtonPress that we will define in Detail.view.xml. As you must be aware that Routing is hash based navigation, here we access the navigation history to find out the previous hash. If we have one, then we just use browser history to go back to the previous page. If we don’t have we execute code oRouter.navTo(“master”, {}, true); This code ensures to navigate to the master page. The second parameter {} can be used to pass additional parameter to this route. The true parameter tells the router to overwrite the current history state with this new one as we are performing back navigation by ourselves.

Our last piece of this SAPUI5 routing and navigation post will to complete the Detail.view.xml file. The bindElement on Detail view is already in place. We use property finding on ObjectAttribute to display additional information. showNavButton=”true” and navButtonPress=”onNavPress” which I have explained in previous paragraph.

<mvc:View 
xmlns:core="sap.ui.core" 
xmlns:mvc="sap.ui.core.mvc" 
xmlns="sap.m" 
controllerName="Amarmn.MyListApp.controller.Detail"
xmlns:html="http://www.w3.org/1999/xhtml">
<Page 
id="detailPage" 
title="Title" 
navButtonPress="onNavPress" 
showNavButton="true">
<content>
<ObjectHeader 
id="objectHeader" 
title="{product>ProductName}" 
number="{product>Quantity}">
<ObjectAttribute 
id="objectAttribute" 
text="ShipperName ={product>ShipperName} 
ExtendedPrice ={product>ExtendedPrice} 
ShippedDate ={product>ShippedDate}">
</ObjectAttribute>
</ObjectHeader>
</content>
</Page>
</mvc:View>

Output of SAPUI5 routing and Navigation example

sapui5 routing and navigation with parameter example
sapui5 routing and navigation with parameter example Mater page
sapui5 routing and navigation with parameter xml view example
sapui5 routing and navigation with parameter xml view example Detail Page

Conclusion:

The article tries to explain the complete process of SAPUI5 Routing and Navigation with Parameter and is a useful SAPUI5 tutorial for beginners.

Leave a Reply

Your email address will not be published. Required fields are marked *