GRC
HR
SCM
CRM
BI
Expand +


Article

 

Routing Concept in SAPUI5 Development: A Primer

by Rehan Zaidi, Senior SAP Technical Consultant

October 19, 2016

The use of routing allows navigation through application views via hashtag-based patterns. This article covers the main steps required to implement routing in an SAPUI5 application and the important classes and methods involved in making a full-fledged example, using a product list.

Routing and navigation are important topics within the SAPUI5 arena. Developers often find the concept of routing difficult to understand. SAP now recommends defining the router configuration in the manifest.json file. SAPUI5 provides a number of classes (with accompanying methods). Though routing can be a difficult concept to learn, it may enable developers to create user-friendly and easy-to-navigate applications in the least possible amount of time.

The aim of this article is to provide an explanation of routing and how to use it in SAPUI5. These are some of the questions this article addresses:

  • What is the routing mechanism and how it is achieved?
  • What are the advantages of using routing?
  • What are some of the most important classes and methods available in SAPUI5 to implement routing?

(Note: The terms hashtag and hash are interchangeable.)

I start with a brief overview of routing and its advantages. I then discuss the classes (and methods) available in the SAPUI5 library for implementing routing in applications. Finally, I show a complete running application that displays a list of products based on Open Data Protocol (OData) from services.odata.org.

This article is meant for ABAP developers and SAPUI5 developers and assumes basic knowledge of SAPUI5 programming. I used the Web Integrated Development Environment (Web IDE) for creating the example shown in this article.

Routing: An Overview

SAPUI5 supports hashtag-based routing and navigation. When using hashtag-based navigation and routing, a change in the hashtag value triggers navigation from one view to another. Simply put, the browser does not have to reload the entire application. A callback is made to the SAPUI5 application in question in the background, based on the value passed after the hashtag symbol (#) in the URL.

SAPUI5 applications may use a router to call one or more views based on the hashtag URL. The router must know how to interpret the URL and show the views. From SAPUI5 version 1.30, SAP recommends defining the routing in the descriptor file (webapp/manifest.json) via routes and targets. The basic steps for implementing routing are:

  • For an application based on SAPUI5, the routing (the entire routes and targets) should be specified in the application descriptor file (webapp/manifest.json).
  • Specify a wrapper view as a point of entry for all routing requests. You also need to initialize a router object to enable the routing mechanism.
  • Define routes and target views based on the text pattern entered by the user after the hashtag in the URL. For example, if the user enters http:___ #/Productdetail/2, then you must specify what view to call and pass on the value 2 to it so that the necessary data can be displayed.If the user clicks product number 2 from a list of products, the URL must automatically change to http:___ #/Productdetail/2.
Important Classes and Methods

Now that you have a basic overview of the routing mechanism, let’s see the main classes and methods. The main classes involved in implementing routing in SAPUI5 applications are:

  • sap.ui.core.routing.Router. This is one of the most important classes. It contains a number of methods for instantiating and initializing a router instance in your application, navigating to a particular route and target upon pattern matching. The name of the class sap.ui.core.routing.Router is specified as the routerclass in the router configuration in the manifest.json. (You will see this in more detail later in the article.) Table 1 shows some of the important methods of the class sap.ui.core.routing.Router.

Method name

Purpose

getRouter  

Returns the reference to a router

initialize 

Initializes a registered router

navTo

Navigates to a particular route

attachMatched

Links a function to the pattern matched

Table 1
Methods of class sap.ui.core.routing.Router

 

  • sap.ui.core.routing.Route. In addition to the sap.ui.core.routing.Router, the class sap.ui.core.routing.Route is also very important. Some of the useful methods that it provides are shown in Table 2.

Method name

Purpose

attachMatched   

 

Links an event-handler Function to the event 'matched' of this sap.ui.core.routing.Route class

attachPatternMatched

 

Links an event-handler Function to the event 'patternMatched' of this sap.ui.core.routing.Route class

destroy   

Destroys a route

getPattern

Returns a route pattern

Table 2
Methods of class sap.ui.core.routing.Route

  • sap.ui.core.UIComponent. The sap.ui.core.UIComponent class also provides a number of methods pertaining to routing and navigation. Some of these are shown in Table 3.

Method name

Purpose

getRouter

Returns the reference to the router instance

getTargets

Returns the reference to the Targets instance

getRouterFor

Static method that takes the respective controller of view and returns the router instance

Table 3
Methods of class sap.ui.core.UIComponent

Some of the useful methods and functions that I use are:

getRoute

This method belongs to the class sap.ui.core.routing.Router. This returns a reference to the route based on the class sap.ui.core.routing.Route. It takes as a parameter the name of the route in question—for example, as shown here: myRouter.getRoute("toProductDetail").

attachMatched

The attachMatched method of the class sap.ui.core.routing.Route is used to link a given route to the event handler function that must be called when the event is matched. This takes as a parameter the function that is to be called.

navTo

This belongs to the class sap.ui.core.routing.Router. It is used for calling a particular route. The first parameter is the name of the route that I defined in the manifest.json. The other optional parameter is used for passing values to the route from the hashtag value entered by the user.

getRouterFor

This static method belonging to class sap.ui.core.UIComponent is one of the most important methods that provides a reference to the router instance from a given controller or view. A simple example is shown here: var myRouter = sap.ui.core.UIComponent.getRouterFor(this);.
Here (this) points to a controller or a view.

getRouter

This is another method for getting the router instance. It belongs to the class sap.ui.core.UIComponent and returns the reference to the router created by UIComponent when the routes in the routing metadata have been specified.

initialize

As the name indicates, this is used for initializing the router in the component. This method belongs to the class sap.ui.core.routing.Router.

Steps for the Implementation of Routing

In this section, I show the steps required to implement a simple routing mechanism. As an example, I create an SAPUI5 app named routingDemo that contains three views for displaying a product list and details. I then display the data from an OData source in the form of a list.

I create an SAPUI5 application and use the Web IDE application in the development of the application. A destination is defined by the name Northwind that points to the services.odata.org. The data source is later defined in the manifest.json file that is generated by the creation of the SAPUI5 application, as shown in Figure 1.

},
        "title": "{{appTitle}}",
        "description": "{{appDescription}}",
        "sourceTemplate": {
            "id": "ui5template.basicSAPUI5ApplicationProject",
            "version": "1.32.0"
        }
        ,
        "dataSources": {
            "mainService": {
                "uri": "/destinations/Northwind/V3/Northwind/Northwind.svc",
                "type": "OData"

            }
        }
    },

Figure 1
Define the data source

The following changes shown in Figure 2 are also made in the file neo-app.json. Here you specify the path pertaining to the destination, the type, name, and description of the Northwind Odata service created earlier.

{
    
"welcomeFile": "/webapp/index.html",
    "routes": [{
           "path": "/resources",
       "target": {
    
              "type": "service",
              "name": "sapui5",
              "entryPath": "/resources"
                    },
             "description": "SAPUI5 Resources"
    },
      {
        "path": "/test-resources",
        "target": { "type": "service", "name": "sapui5", "entryPath": "/test-resources" },
            
        "description": "SAPUI5 Test Resources"
      }
    ,
   { "path": "/destinations/Northwind",
     "target": { "type": "destination", "name": "Northwind" },
     "description": "Northwind Destination"

    }
    ],


"sendWelcomeFileRedirect": true
}
Figure 2
Specify the Northwind destination in the neo-app.json file

I assume that three views are created, namely: App.xml, ProductList.xml, and ProductDetail.xml. First you create a view App.xml. The code for this is shown in Figure 3.

<mvc:View controllerName="RoutingDemo.controller.App" xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc" displayBlock="true">
    <App id="myapp"/>
</mvc:View>
Figure 3
Create a view App.xml

The next view is the ProductList that is used for displaying the list of products (Figure 4). Use the ObjectListItem control for displaying the list of products. A function handleListItemPress is specified that is called when a user clicks a particular product.

<mvc:View controllerName="RoutingDemo.controller.ProductList" xmlns:html="http://www.w3.org/1999/xhtml" xmlns:mvc="sap.ui.core.mvc"
    xmlns="sap.m">

<Page title="{i18n>title}">
<content>
<List items="{/Products}">
<ObjectListItem type="Navigation" press="handleListItemPress"
                title="{ProductName}" number="{= ((${UnitPrice} * 100) / 100).toFixed(2) }"
            numberUnit="USD">
    <attributes>
        <ObjectAttribute text="{QuantityPerUnit}"/>
    </attributes>
        <firstStatus>
                     <ObjectStatus text="{= ${Discontinued}? 'Out of Stock' : 'In Stock' }"
                             state="{= ${Discontinued}? 'Error' : 'Success' }"/>
        </firstStatus>
        </ObjectListItem>
</List>
</content>
</Page>
</mvc:View>
Figure 4
ProductList view

A third view ProductDetail is created that contains the ObjectHeader control (Figure 5). It shows the back button. You specify the handleNavButtonPress as the method to be called when the back button is clicked. This view is able to display the details of a selected product.http://savings.gov.pk/images/spacer.gif

<mvc:View controllerName="RoutingDemo.controller.ProductDetail" xmlns="sap.m" xmlns:mvc="sap.ui.core.mvc">

<Page title="{i18n>Detail}" showNavButton="true"  navButtonPress="handleNavButtonPress">
        <ObjectHeader title="{ProductName}"
                      number="{= ((${UnitPrice} * 100) / 100).toFixed(2) }" numberUnit="USD">
        <statuses>
        <ObjectStatus text="{= ${Discontinued}? 'Out of Stock' : 'In Stock' }"
                             state="{= ${Discontinued}? 'Error' : 'Success' }"/>
        </statuses>
        <attributes>
                <ObjectAttribute text="Product #{ProductID}"/>
                <ObjectAttribute text="Supplier #{SupplierID}"/>
        </attributes>
          </ObjectHeader>
</Page>
</mvc:View>
Figure 5
ProductDetail view

Now that you are familiar with the application in which you have to implement routing, let’s see the required steps.

Step 1. Initialize the router. This is done by calling the initialize method in the component controller file (Component.js):

// enable hash-based routing

this.getRouter().initialize();

Step 2. Add routing configuration in the manifest.json file.  The most important step for routing enablement is to add a routing section to the sap.ui5 section in the descriptor file. This file is already generated in the project and is located in the webapp folder. The manifest file is structured by namespaces. There are specific configuration options possible for each namespace. For my example, the manifest file is shown in Figure 6.

….
        "routing": {
            "config": {
                "routerClass": "sap.m.routing.Router",
                "viewType": "XML",
                "viewPath": "RoutingDemo.view",
                "controlId": "myapp",
                "controlAggregation": "pages",
                "transition" : "flip"
            },
            "routes": [{
                    "pattern": "",
                    "name": "toListPage",
                    "target": "productlist"
                },
                {
                    "pattern": "Productdetail/{Productid}",
                    "name": "toProductDetail",
                    "target": "productdetail"
                }
            ],
            "targets": {
                "productlist": {
                    "viewName": "ProductList",
                    "viewLevel": 1
                },
                "productdetail": {
                    "viewName": "ProductDetail",
                    "viewLevel": 2
                }
            }
        },
Figure 6
The manifest.json file 

Within the routing section, there are three sections that contain parameters used to configure the routing within your application. These sections are config, routes, and targets. Let’s see these sections one by one:

  • config: This section comprises the default values for the router configuration. These values apply to all routes and targets. If required, the parameters in the config section can be changed within the individual route and target specification. The routerClass property may have values such as sap.ui.core.routing.Router. In this case, I have set the routerClass as sap.m.routing.Router since I am implementing an app using the library sap.m. In addition, you also need to specify where your views will be located. Since all the views are based on XML, I have specified the viewType property as XML. Since all views will reside in the view folder of the namespace RoutingDemo, I set the viewPath property to RoutingDemo.view. For the views to be loaded and displayed during pattern matching, you also need to specify the ID of the control used to display the pages. This is done via the property controlId. Since I assigned the id myapp to my app in the App.xml I created earlier, the controlId property is assigned myapp. In addition, the controlAggregation specifies the aggregation to be filled. In the case of myapp, this is pages. The property transition lets you specify how the change in view is to be shown to the user. You can choose between slide, fade, show, and flip.
  • routes: As you can see in Figure 6, each route is comprised of a pattern, a route name, and a target. The target is navigated when a pattern is matched and a route has been hit. The pattern is the part (within the URL) after the hashtag symbol (#). In my example, this is either blank or Productdetail/1, Productdetail/2, or something similar. When mentioning the routes, the sequence of the routes is very important. The first matching route is used by the router. An empty pattern "" specifies the route to be taken on a blank hashtag value. As shown in Figure 6 in this case the target productlist is matched. The name property is used to specify which route is to be navigated. The target property is used to specify the target (views) to be displayed upon a successful route match. The details of these views are in the targets section, below.

(Note: The sap.m.routing.Router is optimized for mobile apps. Using this class lets you add the properties viewLevel and transition, and specify values in the routing configuration.) 

  • targets: The targets section specifies the views that are to be displayed when any of the routes are matched. Whenever a target is selected, the corresponding view specified is loaded and displayed in the aggregation specified with the controlAggregation of the control specified controlId. Every target has a unique name. The name of the view is specified via the viewName. The viewLevel determines the transition path. (This is only relevant for the slide and flip transitions.)

Based on my values, when productlist target is selected on pattern "", the complete path of the view to be loaded is determined by combining the default "viewPath": "RoutingDemo.view" in the config section and "viewName": "ProductList" in the targets section. This leads to the path "RoutingDemo.view.ProductList".

Step 3. Code the ProductList Controller. In this step, I write the necessary coding in the controller ProductList. I use the getRouterFor method using the sap.ui.core.UIComponent class. Finally, the navTo method is called to call the route toProductDetail.

The methods getSource(), getBindingContext(), and getProperty are called  to get a reference to the Product ID selected. I also pass the ID of the selected product. As a parameter, when calling the navTo method, you also pass the ID of the selected Product idOfSelectedProduct that you got in the previous step. The function accepts an evt argument, so you use evt.getSource().getBindingContext() to get the binding context and then use the getProperty method to get the value of the Product ID selected. While calling the getProperty method, the "ProductID" is passed as a parameter.

The code for this is shown in Figure 7.

sap.ui.define([     "sap/ui/core/mvc/Controller" ], function(Controller) {
     "use strict";
    return Controller.extend("RoutingDemo.controller.ProductList", {
            handleListItemPress: function(evt) {
           
               var myRouter = sap.ui.core.UIComponent.getRouterFor(this);
             var idOfSelectedProduct =         
                              evt.getSource().getBindingContext().getProperty("ProductID");

            myRouter.navTo("toProductDetail", {
                        Productid: idOfSelectedProduct
            
             });
    }

  });
});
Figure 7  
ProductList Controller

Step 4. Write the code in the ProductDetail Controller. Now let’s see what coding has to be written on the Detail view controller. Here in the OnInit function, you first get the router using the getRouterFor function. Then use the attachedMatched method to specify the function to be called upon route matching. Within the function onRouteMatched, first call the getParameter to get the arguments parameter of the respective event. Then call the bindElement method to bind the view to the product selected.

Click the back button to call the handleNavButtonPress. In this method you first get the necessary router, and then call the navTo method to call the toListPage route (i.e., the main list view). The code of this is shown in Figure 8.

sap.ui.define(["sap/ui/core/mvc/Controller"], function(Controller) {
    "use strict";
    return Controller.extend("RoutingDemo.controller.ProductDetail", {

    onInit: function() {

        var myRouter = sap.ui.core.UIComponent.getRouterFor(this);
        myRouter.getRoute("toProductDetail").attachMatched(this.onRouteMatched, this);
        },

    onRouteMatched: function(oEvent) {
            var myArgs, thisView;
            myArgs = oEvent.getParameter("arguments");
            thisView = this.getView();
            thisView.bindElement({
                path: "/Products(" + myArgs.Productid + ")"
            });
        },

        handleNavButtonPress: function(evt) {
            var myRouter = sap.ui.core.UIComponent.getRouterFor(this);
            myRouter.navTo("toListPage");
        }
    });
});

Figure 8  
ProductDetail Controller

Putting It All Together

Once the steps are completed, the app has a fully functional routing. Upon execution of the app, you can display a product list, as shown in Figure 9.


Figure 9
Product list

At this point, the URL is displayed with the hashtag symbol (#) followed by no characters (the URL shown in Figure 9 is not the complete URL). The view ProductList is displayed and the route target productlist is loaded.  

Upon clicking the second product (Chang, in this example – the first product is not shown), the relevant product details are displayed (Figure 10). At this point, you have the target productDetail matched. If the user directly enters the URL shown in Figure 10, the respective product appears.


Figure 10
Product detail

The URL changes to http://__#Productdetail/2 and the ProductDetail view is loaded.

It is also possible to go directly to the given product by typing the URL ending with #Product/2

http://__#Productdetail/2.

This article explains the function of the router and navigation. You may try to add a new view to the application by using the name notfound to display when the user specifies an invalid pattern.


An email has been sent to:





 

Rehan Zaidi

Rehan Zaidi (erpdomain@gmail.com) is a consultant for several international SAP clients (both on-site and remotely) on a wide range of SAP technical and functional requirements, and also provides writing and documentation services for their SAP- and ABAP-related products. He started working with SAP in 1999 and writing about his experiences in 2001.



More from SAPinsider



COMMENTS

Please log in to post a comment.

No comments have been submitted on this article. Be the first to comment!


SAPinsider
FAQ