Now that we have covered all kinds of tests for navigation, we introduce our Post page that shows details of a post in the bulletin board. To achieve this, we have to introduce a new view/controller pair and adjust the routing of the application.
You can view and download all files in the Explored app in the Demo Kit at Testing - Step 9.
#!js{ "_version": "1.1.0", … "sap.ui5": { … "routing": { "config": { "routerClass": "sap.m.routing.Router", "viewType": "XML", "viewPath": "sap.ui.demo.bulletinboard.view", "controlId": "app", "controlAggregation": "pages" }, "routes": [ { "pattern": "", "name": "worklist", "target": "worklist" }, { "pattern": "Post/{postId}", "name": "post", "target": "post" } ], "targets": { "worklist": { "viewName": "Worklist", "viewId": "worklist", "viewLevel": 1 }, "post": { "viewName": "Post", "viewId": "post", "viewLevel": 2 } } } } }
We have already used the #/Posts/{postId} hash in our tests and a view called the Post page, so we will now add a route and a target to the routing configuration of the descriptor with these patterns. It is simply defining a mandatory routing parameter postId that we fill with the ID from the model when navigating. The target configuration references a view called Post with a view level deeper than the home page. For more information, see the Navigation and Routing tutorial.
#!xml<mvc:View
controllerName="sap.ui.demo.bulletinboard.controller.Worklist"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core"
xmlns:semantic="sap.m.semantic">
<semantic:FullscreenPage
id="page"
title="{i18n>worklistViewTitle}">
<semantic:content>
<Table …>
…
<items>
<ColumnListItem
type="Navigation"
press="onPress">
…
</ColumnListItem>
</items>
</Table>
</semantic:content>
…
</semantic:FullscreenPage>
</mvc:View>
We configure the table items to be of type Navigation, so a user can trigger the navigation by choosing an item. When a press event is triggered, the onPress handler is called to navigate to the Post page.
#!js/*global history*/
sap.ui.define([
'sap/ui/demo/bulletinboard/controller/BaseController',
'sap/ui/model/json/JSONModel',
'sap/ui/demo/bulletinboard/model/formatter'
], function (BaseController, JSONModel, formatter) {
"use strict";
return BaseController.extend("sap.ui.demo.bulletinboard.controller.Worklist", {
…
/* =========================================================== */
/* event handlers */
/* =========================================================== */
…
/**
* Event handler when a table item gets pressed
* @param {sap.ui.base.Event} oEvent the table selectionChange event
* @public
*/
onPress: function (oEvent) {
this.getRouter().navTo("post", {
// The source is the list item that got pressed
postId: oEvent.getSource().getBindingContext().getProperty("PostID")
});
},
…
});
});
The press handler function instructs the router to navigate to the post pattern with the PostID from the binding context of the currently selected item. This fills the mandatory URL parameter, navigates to the post page, and updates the hash automatically.
#!xml<mvc:View
controllerName="sap.ui.demo.bulletinboard.controller.Post"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:semantic="sap.m.semantic">
<semantic:FullscreenPage
id="page"
busy="{postView>/busy}"
busyIndicatorDelay="0"
navButtonPress="onNavBack"
showNavButton="true"
title="{i18n>objectTitle}">
<semantic:content>
<ObjectHeader
id="objectHeader"
title="{Title}"
number="{Price}"
numberUnit="{Currency}">
</ObjectHeader>
</semantic:content>
</semantic:FullscreenPage>
</mvc:View>
Control with the ID page on this view
title of the post we navigate to
Back button to navigate back to the home page
#!jssap.ui.define([
'sap/ui/demo/bulletinboard/controller/BaseController',
'sap/ui/model/json/JSONModel',
'sap/ui/demo/bulletinboard/model/formatter'
], function (BaseController, JSONModel, formatter) {
"use strict";
return BaseController.extend("sap.ui.demo.bulletinboard.controller.Post", {
formatter: formatter,
/* =========================================================== */
/* lifecycle methods */
/* =========================================================== */
/**
* Called when the worklist controller is instantiated.
* @public
*/
onInit: function () {
// Model used to manipulate control states. The chosen values make sure,
// detail page is busy indication immediately so there is no break in
// between the busy indication for loading the view's meta data
var oViewModel = new JSONModel({
busy: false
});
this.getRouter().getRoute("post").attachPatternMatched(this._onPostMatched, this);
this.setModel(oViewModel, "postView");
},
/* =========================================================== */
/* event handlers */
/* =========================================================== */
/**
* Navigates back to the worklist
* @function
*/
onNavBack: function () {
this.myNavBack("worklist");
},
/* =========================================================== */
/* internal methods */
/* =========================================================== */
/**
* Binds the view to the post path.
*
* @function
* @param {sap.ui.base.Event} oEvent pattern match event in route 'object'
* @private
*/
_onPostMatched: function (oEvent) {
var oViewModel = this.getModel("postView"),
oDataModel = this.getModel();
this.getView().bindElement({
path: "/Posts('" + oEvent.getParameter("arguments").postId + "')",
events: {
dataRequested: function () {
oDataModel.metadataLoaded().then(function () {
// Busy indicator on view should only be set if metadata is loaded,
// otherwise there may be two busy indications next to each other on the
// screen. This happens because route matched handler already calls '_bindView'
// while metadata is loaded.
oViewModel.setProperty("/busy", true);
});
},
dataReceived: function () {
oViewModel.setProperty("/busy", false);
}
}
});
}
});
});
The controller of the Post page needs to take care of the data binding when a navigation event has happened. In the init function of the controller we define a local view model and attach to the routing event. When the routing event is triggered, we bind the view to the post with the specified ID.