alterno logo 2021-02

Hi friends!

This week we will go through the technical aspects of such an important issue as routing (navigation).

We will be answering these questions:

  1. What is SAPUI5 routing and what is it for?
  2. Important things to know about routing in SAPUI5
  3. Recommended components
  4. What is a “Fragment” and what is it for?
  5. Features of the configuration and navigation component of sap.m.SplitApp
  6. Сross application navigation
  7. Several routings in one controller
  8. How to optimize routing performance

1. What is “SAPUI5  Routing” and what is it for?

Routing is a navigation (transition) from one page (View) to another.

In SAPUI5, navigation is not between pages, but between Views.

2. Important things to know about routing in SAPUI5

  • routing is possible only between Views. Navigating between Fragments is impossible, since Fragment is part of a View
  • you can only switch between Fragments (navigation and switching are not the same)
  • each View must have its own controller – since it is initializing (assigning) routing. Same controller can be used in multiple views, though
  • routing configuration is carried out in the manifest.json file

3. Recommended components

We recommend using standard components, such as:

  • sap.m.App
  • sap.m.Page
  • sap.m.SplitApp
  • sap.ui.core.Fragment

If you have a simple application, in which it is enough to switch from one page to another – then you create the required number of View and switch (navigate) between them (that is, navigation will occur in one container).

If you have a more complex application, we recommend using the sap.m.SplitApp component – containing two navigation containers. This component also allows you to work in navigation mode in a single container (property mode=”HideMode” – master area is hidden initially both in portrait and landscape). At any time, you can switch back to dual-container mode (property mode=”ShowHideMode” – master will automatically be hidden in portrait mode).

When to use sap.m.SplitApp:

  • you need to review and process different items quickly with minimal navigation

When not to use sap.m.SplitApp:

  • you need to support complex filters for the list of items
  • you need to see different attributes for each item in the list, and compare these values across items
  • you want to display a single object. Do not use the master list to display different facets of the same object

4. What is a “Fragment” and what is it for?

Fragments is a standard component of the sap.ui.core.Fragment library, a lightweight stand-alone user interface control. The content of the fragment is imported and fully integrated into the view.

The fragment does not have its own controller – it uses the methods of the controller of the “hosting” view.

Use-cases for Fragments are e.g.:

  • Re-using the same XML code in several places
  • Splitting large XML views into logical parts

5. Features of the configuration and navigation component sap.m.SplitApp

In SAPUI5 there are 2 general concepts of routing:

  • Single view injection
  • Multiple views injection simultaneously

If you have a more complex application, we recommend using the sap.m.SplitApp component. It contains two NavContainers, if they are running on a tablet or desktop computer, and one if it is running on a phone. The display of the NavContainer master depends on the device mode and the SplitApp mode (portrait / landscape).

The SplitApp divides the screen into two areas:

  • Master area – contains a list of available items where the user can search and filter
  • Details area – contains a control which shows further details on the item(s) selected from the master view.

Both areas have separate headers and footer bars with navigation and actions.

This component also allows you to work in navigation mode in a single container (property mode=”HideMode” – master area is hidden initially both in portrait and landscape). At any time, you can switch back to dual-container mode (property mode=”ShowHideMode” – master will automatically be hidden in portrait mode). This property is relevant (makes sense) for tablets and desktop versions.

In which scenarios is this component used:

  • fixed master area (without navigation) and switchable detail area (navigation will occur only in the detail area):
<mvc:View controllerName ="path_to_controller"
          xmlns:mvc      ="sap.ui.core.mvc"
          xmlns:core     ="sap.ui.core"
          xmlns          ="sap.m">
   <SplitApp id="splitApp>
      <masterPages>
         <List>
            <CustomListItem>
               <Text text=”” />
            </CustomListItem>
         </List>
         or put the code in the fragment file and enter it here:
         core:Fragment fragmentName="path_to_fragment_file" type="XML" />
      </masterPages>
      <detailPages />
   </SplitApp>
</mvc:View>

And configure your “manifest.json“ file “config” subsection in “routing” section (that aggregation will only occur in details area and which View will be displayed by default in the details area when the application is started):

"config" : {
   "routerClass"        : "sap.m.routing.Router",
   "viewType"           : "XML",
   "viewPath"           : "path_to_view_folder",
   "controlId"          : "main_container_id",
   "controlAggregation" : "detailPages",
   "transition"         : "slide",
   "bypassed"           : {
      "target"          : "target_name_for_details_area"
    }
}

  • switchable master area and detail area (navigation will occur in both containers):
<mvc:View controllerName="path_to_controller"
          xmlns:mvc     ="sap.ui.core.mvc"
          xmlns         ="sap.m">
   <SplitApp id="splitApp>
      <masterPages />
      <detailPages />
   </SplitApp>
</mvc:View>

And configure your “manifest.json“ file “config” subsection in “routing” section (that aggregation will occur in both areas and which views will be displayed by default when you run the application):

"config" : {
   "routerClass"        : "sap.m.routing.Router",
   "viewType"           : "XML",
   "viewPath"           : "path_to_view_folder",
   "controlId"          : "main_container_id",
   "controlAggregation" : "pages",
   "transition"         : "slide",
   "bypassed"           : {
      "target" : [
         "target_name_for_master_area",
         "target_name_for_details_area"
      ]
    }
}

In order for your View to be displayed in the necessary container (master area or detail area), you need to in the file manifest.json in the subsection “targets” in “routing” section (which describes what routing refers to) in the parameters of the target name, specify in the parameter controlAggregation indicate where the aggregation will occur (masterPages or detailPages):

"routes" : [
   {
      "pattern" : "EmployeesList,
      "name"    : "EmployeesList",
      "target"  : “EmployeesList”
   },
   {
      "pattern" : "Details/{passportNumber}”,
      "name"    : "Details",
      "target"  : “Details”
   }
],
"targets": {
   "EmployeesList" : {
      "viewType"           :"XML",
      "transition"         :"slide",
      "clearAggregation"   : true,
      "viewName"           : "path_to_view_file",
      "viewLevel"          : 1,
      "controlAggregation" : "masterPages"
   },
   "Details" : {
      "viewType"           :"XML",
      "transition"         :"slide",
      "clearAggregation"   : true,
      "viewName"           :"path_to_view_file",
      "viewLevel"          : 1,
      "controlAggregation: detailPages"
   },
}

For simultaneous routing in the master area and in the details area, in the “routes” subsection in “routing” section, in the “target” routing parameter, specify two targets (for the master and details):

"routes" : [
   {
      "pattern" : "",
      "name"    : "Home",
      "target"  : [“NotSelected”, “EmployeesList”]
   }
],
"targets" : {
   "EmployeesList" : {
      "viewType"           : "XML",
      "transition"         : "slide",
      "clearAggregation"   : true,
      "viewName"           : "path_to_view_file",
      "viewLevel"          : 1,
      "controlAggregation" : "masterPages"
   },
   "NotSelected" : {
      "viewType"           : "XML",
      "transition"         : "slide",
      "clearAggregation"   : true,
      "viewName"           : "path_to_view_file",
      "viewLevel"          : 1,
      "controlAggregation" "detailPages"
   },
}

Important:

  • On a mobile device, the sap.m.SplitApp component will be displayed with only one navigation container. If simultaneous routing is used, the mobile device will display the last specified name in the “target” parameter of the “routing” section of the “routes” subsection.
  • The sap.m.SplitApp component will display the specified View in the corresponding navigation container – master area or details area (which is specified in the “controlAggregation” parameter)
  • On a mobile device, events will occur only for one navigation container – which will eventually be shown on the screen (in the desktop version – for both)

6. Сross application navigation

The CrossApplicationNavigation service (Unified Shell’s) – which allows to navigate to external targets or create links to external targets. In simple terms, it is a service that allows you to navigate from one application to another. This interface is for usage by applications or shell renderers (containers).

A few words about the basic concepts of cross-navigation:

Hash – is the optional last part of a URL, introduced by a hash tag #. It is typically used to identify a portion of that URL (document).

URL – a reference to a web resource that specifies its location on a computer network.

Semantic object – represents a business unit (for example, a contract or product). Using semantic objects, you can link applications that reflect a specific scenario.

You can use semantic objects supplied by SAP, or create new ones.

In simple words, the Semantic object links the launchpad tile with an application (for example: UI5 with the path and name of the component).

Action – describes which operation (for example, display or SendToApproveOrder) is intended to be performed on a semantic object (such as an OrderConfirmation or Product).

Usage example (scenario):

  • there is a launchpad with applications “Employees” and “Contracts”
  • each employee has a signed contract with the company in which he works
  • we need to go from the “Employees” application (from the screen with information about a specific employee) to the details of the contract signed with this employee (that is, on the contract detail screen to “Contract” application)

We need to know the exact hash of the link where the screen is located:

http://ourexample.company.local:1000/sap/bc/ui5_ui5/ui2/ushell/shells/abap/FioriLaunchpad.html#Contracts-display&/ContractDetails/contract_number

Important:

  • Never use (do not get attached) to the full URL! In different systems, the URL will also be different (eg, development, testing and production systems)

In our example:

  • the hash is:

#Contracts-display&/ContractDetails/contract_number

  • semantic object is:

Contracts

  • action is:

display&/ContractDetails/contract_number

Now that we know all the parameters, we can write a function for cross-navigation:

goToContractDetails : function (contractNumber) {
   var oCrossAppNavigator = sap.ushell.Container.getService("CrossApplicationNavigation");
   var hash               = (oCrossAppNavigator && oCrossAppNavigator.hrefForExternal({
      target : {
         semanticObject : "Contracts",
         action         : "display&/ContractDetails/" + contractNumber
      },

   })) || "";     // generate the Hash to display a Contract

   oCrossAppNavigator.toExternal({
      target : {
         shellHash : hash
      }
   });            // navigate to “Contracts” application
}

7. Several routing in one controller

Sometimes it is required that the routing can be processed in several controllers.

All that needs to be done for this is to fix the handler for one more routing in the controller:

onInit : function() {
   var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
   oRouter.getRoute("ContractDetails").attachPatternMatched(this._onDetailsMatched,  this);
   oRouter.getRoute("ContactsList").attachPatternMatched(this._onContactListMatched, this);
},

_onDetailsMatched : function(event) {
}

_onContactListMatched : function(event) {
}

Important:

  • It is important to understand that each time you navigate to View, to which routing is assigned to manifest.json, the method assigned to this routing name will also be called in each controller (provided that the controller already exists, i.e. loaded into memory)!

8. How to optimize performance

  • do not use timeouts (setTimeout() )
  • handle user actions using component events – for example, component sap.m.SplitApp has a series of events for each navigation container:
  • do not use “heavy” processing on the UI side (let the backend do the job)
  • build the right call chain
  • initialize all models in the Init() function of the Component.js file
  • perform initialization by default in the standard controller functions – onInit() and onAfterRendering()
  • not complex processing that must be repeated every time you enter (navigate) to the View – perform in the routing method
  • use inheritance in CSS
  • when working with methods for determining geolocation – use minimal timeout values in the properties of methods
  • reduce calls to the backend (for example, store unchanged, not large and often used information in the JSON model)

Any questions?

Just write us a message!

Fill out the form and we will be in touch as soon as possible!