Show TOC

Step 32: Routing with ParametersLocate this document in the navigation structure

We can now navigate between the overview and the detail page, but the actual item that we selected in the overview is not displayed on the detail page yet. A typical use case for our app is to show additional information for the selected item on the detail page. To make this work, we have to pass over the information which item has been selected to the detail page and show the details for the item there.

Preview
Figure 1: The selected invoice details are now shown in the details page
Coding

You can view and download all files in the Explored app in the Demo Kit under Walkthrough - Step 32.

webapp/manifest.json
{
  "_version": "1.1.0",
  …
  "sap.ui5": {
	…
	"routing": {
	  "config": {
		"routerClass": "sap.m.routing.Router",
		"viewType": "XML",
		"viewPath": "sap.ui.demo.wt.view",
		"controlId": "app",
		"controlAggregation": "pages"
	  },
	  "routes": [
		{
		  "pattern": "",
		  "name": "overview",
		  "target": "overview"
		},
		{
		  "pattern": "detail/{invoicePath}",
		  "name": "detail",
		  "target": "detail"
		}
	  ],
	  "targets": {
		"overview": {
		  "viewName": "Overview"
		},
		"detail": {
		  "viewName": "Detail"
		}
	  }
	}
  }
}

We now add a navigation parameter invoicePath to the detail route so that we can hand over the information for the selected item to the detail page. Mandatory navigation parameters are defined with curly brackets.

webapp/view/Detail.view.xml
<mvc:View
	controllerName="sap.ui.demo.wt.controller.Detail"
	xmlns="sap.m"
	xmlns:mvc="sap.ui.core.mvc">
	<Page
		title="{i18n>detailPageTitle}">
		<ObjectHeader
			intro="{invoice>ShipperName}"
			title="{invoice>ProductName}"/>
	</Page>
</mvc:View>

We add a controller that will take care of setting the item's context on the view and bind some properties of the ObjectHeader to the fields of our invoice model. We could add more detailed information from the invoice object here, but for simplicity reasons we just display two fields for now.

webapp/controller/InvoiceList.controller.js
sap.ui.define([
	"sap/ui/core/mvc/Controller",
	"sap/ui/model/json/JSONModel",
	"sap/ui/demo/wt/model/formatter",
	"sap/ui/model/Filter",
	"sap/ui/model/FilterOperator"
], function (Controller, JSONModel, formatter, Filter, FilterOperator) {
	"use strict";
	return Controller.extend("sap.ui.demo.wt.controller.InvoiceList", {
		…

		onPress: function (oEvent) {
			var oItem = oEvent.getSource();
			var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
			oRouter.navTo("detail", {
				invoicePath: oItem.getBindingContext("invoice").getPath().substr(1)
			});
		}
	});
});

The control instance that has been interacted with can be accessed by the getSource method that is available for all SAPUI5 events. It will return the ObjectListItem that has been clicked in our case. We will use it to pass the information of the clicked item to the detail page so that the same item can be displayed there.

In the navTo method we now add a configuration object to fill the navigation parameter invoicePath with the current information of the item. This will update the URL and navigate to the detail view at the same time. On the detail page, we can access this context information again and display the corresponding item.

To identify the object that we selected, we would typically use the key of the item in the back-end system because it is short and precise. For our invoice items however, we do not have a simple key and directly use the binding path to keep the example short and simple. The path to the item is part of the binding context which is a helper object of SAPUI5 to manage the binding information for controls. The binding context can be accessed by calling the getBindingContext method with the model name on any bound SAPUI5 control. We need to remove the first / from the binding path by calling .substr(1) on the string because this is a special character in URLs and is not allowed, we will add it again on the detail page.

webapp/controller/Detail.controller.js (New)
sap.ui.define([
	"sap/ui/core/mvc/Controller"
], function (Controller) {
	"use strict";
	return Controller.extend("sap.ui.demo.wt.controller.Detail", {
		onInit: function () {
			var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
			oRouter.getRoute("detail").attachPatternMatched(this._onObjectMatched, this);
		},
		_onObjectMatched: function (oEvent) {
			this.getView().bindElement({
				path: "/" + oEvent.getParameter("arguments").invoicePath,
				model: "invoice"
			});
		}
	});
});

Our last piece to fit the puzzle together is the detail controller. It needs to set the context that we passed in with the URL parameter invoicePath on the view, so that the item that has been selected in the list of invoices is actually displayed, otherwise, the view would simply stay empty.

In the init method of the controller we fetch the instance of our app router and attach to the detail route by calling the method attachPatternMatched on the route that we accessed by its name. We register an internal callback function _onObjectMatched that 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.

In the _onObjectMatched method that is triggered by the router we receive an event that we can use to access the URL and navigation parameters. The arguments parameter will return an object that corresponds to our navigation parameters from the route pattern. We access the invoicePath that we set in the invoice list controller and call the bindElement function on the view to set the context. We have to add the root / in front of the path again that was removed for passing on the path as a URL parameter.

The bindElement function is creating a binding context for a SAPUI5 control and receives the model name as well as the path to an item in a configuration object. This will trigger an update of the UI controls that we connected with fields of the invoice model. You should now see the invoice details on a separate page when you click on an item in the list of invoices.

Conventions
  • Define the routing configuration in the AppDescriptor