The purpose of this blog post is to show how to implement Split-Screen layout based on Fiori Design Guidelines using SAPUI5 routing API. The full working example with the source code is available here 

What is Fiori Split-Screen Layout?

The Split-Screen layout is a master/detail pattern the has the following characteristics:

  • The user can quickly scan the items on the left and see the detail of the chosen item in the right.
  • The detail area may also have a list where users can drill-down for additional details.
  • The user can navigate back to the previous page.

For example, a list of orders on the left side and order details on the right side. The order details area contains a list of products of that specific order. The user can drill down into the details of each product. In the product details page, the user can navigate back to the order detail page.

In this post, we are going to implement this scenario as below screenshot.

For more information about the Split-Screen layout click here

How to implement?

Structure:

As you can see above, we have 3 views:

  1. Master view: This view will contain the list of orders.
  2. Detail1 view: This view will contain order details, ie. the list of products
  3. Detail2 view: This view will contain product details (name and id).

In addition, we will have a component controller (Component.js) that contains routing metadata and configuration.

For more information about the component controller click here

Router Configuration in Component.js:

In the Component.js, we are going to define 3 routes:

  1. master: this will be the default route.
  2. orderDetails: this will be used to navigate to a specific order. For example, route #/orders/3 will navigate to the order of ID=3. Since we want to show the master with order list in the left and order details on the right, there will be two targets: Master and Details1
  3. productDetails: this will be used to navigate to a specific product. For example, route #/orders/2/product/1 will navigate to the product of ID=1 in order of ID=2. Since we want to show the master with order list in the left and product details on the right, there will be two targets: Master and Detail2

The complete configuration is as follows:

routing: {
	config: {
		routerClass: "sap.m.routing.Router",
		viewPath: "sap.ui.core.sample.RoutingMasterDetail.routingApp.view",
		controlId: "rootControl",
		viewType: "XML"
	},
	routes: [
		{
			name: "master",
			pattern: "",
			target: ["master"]
		},
		{
			name: "orderDetails",
			pattern: "orders/:orderId:",
			target: ["master", "orderDetails"]
		},
		{
			name: "productDetails",
			pattern: "orders/:orderId:/products/:productId:",
			target: ["master", "productDetails"],
		}
	],
	targets: {
		master: {
			viewName: "Master",
			controlAggregation: "masterPages",
			viewLevel: 0
		},
		orderDetails: {
			viewName: "Detail1",
			controlAggregation: "detailPages",
			title: {
				parts: ["orderName"],
				formatter: "jQuery.sap.formatMessage"
			},
			viewLevel: 1
		},
		productDetails: {
			viewName: "Detail2",
			controlAggregation: "detailPages",
			title: {
				parts: ["productName"],
				formatter: "jQuery.sap.formatMessage"
			},
			viewLevel: 2
		}
	}
}

Drill-down from Master to Detail1:

Now we want to drill-down from the master (order list) to order details. In the master view, we have to attach “press” event on the ListItem

<StandardListItem title="{orderName}" 
	type="Active"
	press="onSelectionChange"/>

In the controller of the Master, we will use the navTo method of the Router. navTo method expects the following parameters:

  • route name (mandatory): This is the name of the route that we want to use. In this case,  we want to navigate to order details view (Detail1), so we will use “orderDetails”.
  • parameters (optional): Here we can pass parameters to the next view. In our case, the order details view needs to know the order Id of the item we press on.
  • replace (optional): Here we can control the browser history behavior. If true, the route will not be added to the browser history and if false the route will be added to the browser history so that the back button will remember the route.
onSelectionChange: function(oEvent) {
	var sOrderId = oEvent.getSource().getSelectedItem().getBindingContext().getProperty("orderId")
	this.getOwnerComponent().getRouter()
		.navTo("orderDetails", 
			{orderId:sOrderId}, 
			!Device.system.phone);
}

Drill-down from Detail1  to Detail2:

Similarly, we will use “press” event and navTo method to navigate from order details view (Detail1) to product detail (Detail2). However, this time we will use “productDetails route and we will pass two parameters: orderId and productId:

<StandardListItem title="{productName}" 
	type="Active"
	press="onSelectionChange"/>

 

onSelectionChange: function(oEvent) {
	var sProductId = oEvent.getSource().getBindingContext().getProperty("productId");
	this.getOwnerComponent().getRouter()
		.navTo("productDetails", 
			{orderId:this._orderId, productId: sProductId});
}

Navigating back from Detail1 (order detail) to Master:

According to Split-Screen layout in Fiori Design Guidelines, the master list and the details are split into two separate pages on narrow screens for phones. So, our goal here is to show the back button only on phones. To achieve this, first we need a way to identify the user’s device. We can check the user’s device using the Device API, where the sap.ui.Device class provides the needed information.

Create a new model that contains the device information:

createDeviceModel : function () {
	var oModel = new JSONModel(Device);
	oModel.setDefaultBindingMode("OneWay");
	return oModel;
}
this.setModel(this.createDeviceModel(), "device");

Show the back navigation button only on phones:

The Page component has property showNavButton which expect boolean value. So, here we will bind it to /system/phone

<Page
	title="{orderName}"
	navButtonPress="onNavBack"
	showNavButton="{device>/system/phone}">

In the event handler method, we will use History API to use browser history and navigate back.

onNavBack : function() {
	var sPreviousHash = History.getInstance().getPreviousHash();
	if (sPreviousHash !== undefined) {
		history.go(-1);
	} else {
		this.getOwnerComponent().getRouter().navTo("master", {}, true);
	}
}

Navigating back from Detail2 (product detail) to Detail1 (order detail):

This should be straight forward. We will use the same technique as in the previous step. But this time showNavButton is always true because the device doesn’t matter.

<Page
	title="{productName}"
	navButtonPress="onNavBack"
	showNavButton="true">

Also, we will use History API to handle the onNavBack press event:

onNavBack : function () {
	var sPreviousHash = History.getInstance().getPreviousHash();
	if (sPreviousHash !== undefined) {
		window.history.go(-1);
	} else {
		this.getOwnerComponent().getRouter()
			.navTo("orderDetails", 
				{orderId:0}, !Device.system.phone);
	}
}

Handling The Browser Window’s Title:

So far, we implemented the drill-down and navigation back scenarios, so the user can navigate to different views within the application. But when you look into the browser history, the window title remains the same which is confusing for the user. The objective here to change the browser title based on the view we are visiting.

As of version 1.42, Routing APIs provide the possibility to define titles declaratively in its configuration. In order to achieve this, we need to define title and bind it to the orderName property as below:

title: {
	parts: ["orderName"],
	formatter: "jQuery.sap.formatMessage"
}

In order to get notified once the title is changed, you can register to the ‘titleChanged’ event on the Router instance. The ‘titleChanged’ event is then fired once a target which has a title options set is displayed or the title of a displayed target is changed.

this.getRouter().attachTitleChanged(function(oEvent){
	document.title = oEvent.getParameter("title");
});

For more information of using title in Router configuration click here

We also have to do the same thing for product details route.

To report this post you need to login first.

1 Comment

You must be Logged on to comment or reply to a post.

  1. vinayak khosla

    Hi Fahad,

    Great Post. I have one question, How to show first order’s detail i.e. Master (first order selected) and Detail1 (with detail of the first order from master) when the application will be opened/initialized the first time.

    (0) 

Leave a Reply