Skip to Content
Author's profile photo Mark Teichmann

Cross Application Navigation between SAPUI5 applications

At SAP Inside Track Hamburg 2016 together with Remo Bettin we demonstrated during a short lightning talk how to do Cross Application Navigation between different applications on the Fiori Launchpad.

While this topic is covered in SAPUI5 help it is still not so easy to implement it. Therefore we built a small demo application in order to demonstrate how to use it.

Based on the entities of the Northwind OData Service we created four separate SAPUI5 Applications, one for orders, others for the corresponding customers and suppliers of the orders shown in the Orders app. The last application we used is based on the categories entity of the Northwind service.

All these applications are added to the Fiori Launchpad in the HANA Cloud Platform (which is named flpnwc there and available as a subscription in the HCP account).

Bildschirmfoto 2016-06-15 um 22.03.16.png

Picture 1: Fiori Launchpad in HCP showing the applications

In order to be able to use cross app navigation all applications need to be assigned to intents. The intent consists of a semantic object and an action on this object. For our applications we used the entity name as semantic object and all applications use the “display” action to display some data. The semantic object is declared in the manifest.json from the SAPUI5 app.

Bildschirmfoto 2016-06-20 um 15.26.11.png

Picture 2: Navigation properties in manifest.json

Once an application is reached it uses inner app navigation to find the correct route to a view.

The following example shows the routes in the supplier app. Here to navigate to a supplier detail we use a route “Suppliers/5” in order to open the object view and show details of supplier with ID 5.

Bildschirmfoto 2016-06-20 um 15.23.49.png

Picture 3: Routes in manifest.json

In order to navigate from one application to another in the Fiori Launchpad (FLP) we need to implement some code at the following locations:

1. The starting point of our CrossApp-Navigation is pressing on the supplier column in the Orders app. There we added the onPressSupplier-event in the column of the detail view where the supplier is shown

onPressSupplier: function(oEvent) {
  var supplier = oEvent.getSource().getBindingContext().getProperty("Product/SupplierID"); // read SupplierID from OData path Product/SupplierID
  var oCrossAppNavigator = sap.ushell.Container.getService("CrossApplicationNavigation"); // get a handle on the global XAppNav service
  var hash = (oCrossAppNavigator && oCrossAppNavigator.hrefForExternal({
  target: {
  semanticObject: "Supplier",
  action: "display"
  params: {
  "supplierID": supplier
  })) || ""; // generate the Hash to display a Supplier
  target: {
  shellHash: hash
  }); // navigate to Supplier application

2. In the onInit-Event of the Master view of the Suppliers App we attach the event _onMasterMatched:

this.getRouter().getRoute("master").attachPatternMatched(this._onMasterMatched, this);

3. In the _onMasterMatched we read the Startup parameters where we get the Supplier ID:

_onMasterMatched :  function() {
  var supplierID;
  var startupParams = this.getOwnerComponent().getComponentData().startupParameters; // get Startup params from Owner Component
  if ((startupParams.supplierID && startupParams.supplierID[0])) {
  this.getRouter().navTo("object", {
  supplierID: startupParams.supplierID[0]  // read Supplier ID. Every parameter is placed in an array therefore [0] holds the value
  }, true);
  } else {
  function(mParams) {
  if (mParams.list.getMode() === "None") {
  supplierID = mParams.firstListitem.getBindingContext().getProperty("SupplierID");
  this.getRouter().navTo("object", {
  supplierID: supplierID
  }, true);
  function(mParams) {
  if (mParams.error) {


Based on the entities of the Northwind OData Service we created four separate SAPUI5 Applications. In the Orders application you see a Master-Detail navigation for selecting an order and displaying the corresponding order details.

We select one order in the left master view and after that click on Customer “Vins et alcools Chevalier” with CustomerID “VINET”:

Bildschirmfoto 2016-06-15 um 22.10.32.png

This creates the link “#Customer-display?customerID=VINET&/Customers/VINET”.

The action “display” in the application with semantic object “Customer” is invoked.

The startup parameter is “customerID=VINET”. This invokes the inner app navigation in the Customer app resolving in the URL fragment “/Customers/VINET” which is the route to the object view and shows the details view of customer “Vins et alcools Chevalier”.

Bildschirmfoto 2016-06-15 um 22.11.26.png

Similar routing happens when clicking on the supplier in the orders app:

Bildschirmfoto 2016-06-15 um 22.12.02.png


When using the method you can optionally provide a component (the root component of the application). Unfortunately in the help you can’t find a hint for what this could be used. Maybe somebody knows the intent of this parameter?

Hopefully this blog post will be of some help for your implementation of Cross application navigation. In case you still have questions I would be happy to answer them if possible.



Assigned Tags

      You must be Logged on to comment or reply to a post.
      Author's profile photo balaji kiran
      balaji kiran

      Really appreciate  your blog. Really its helps alot.

      Author's profile photo Former Member
      Former Member

      Can you provide the manifest.json code? I have implemented same code in my system but i did not understand mainfest.json code in your blog

      cross application navigation not working in my application and console did not provided any error.  i did not able to figureout error..

      Author's profile photo Mark Teichmann
      Mark Teichmann

      Sorry for my late response. I did not get any notification from the new community platform...


      This is the manifest.json from one of the apps.

      	"_version": "1.3.0",
      	"": {
      		"_version": "1.3.0",
      		"id": "sithhorders",
      		"type": "application",
      		"i18n": "i18n/",
      		"title": "{{appTitle}}",
      		"description": "{{appDescription}}",
      		"applicationVersion": {
      			"version": "1.0.0"
      		"dataSources": {
      			"mainService": {
      				"uri": "/destinations/northwind/V2/Northwind/Northwind.svc/",
      				"type": "OData",
      				"settings": {
      					"odataVersion": "2.0",
      					"localUri": "localService/metadata.xml"
      		"sourceTemplate": {
      			"id": "sap.ui.ui5-template-plugin.2masterdetail",
      			"version": "1.36.2"
      		"crossNavigation": {
      			"inbounds": {
      				"intent1": {
      					"signature": {
      						"parameters": {},
      						"additionalParameters": "allowed"
      					"semanticObject": "Orders",
      					"action": "display",
      					"title": "Orders",
      					"icon": "sap-icon://sales-order"
      	"sap.ui": {
      		"_version": "1.3.0",
      		"technology": "UI5",
      		"icons": {
      			"icon": "sap-icon://detail-view",
      			"favIcon": "",
      			"phone": "",
      			"phone@2": "",
      			"tablet": "",
      			"tablet@2": ""
      		"deviceTypes": {
      			"desktop": true,
      			"tablet": true,
      			"phone": true
      		"supportedThemes": [
      	"sap.ui5": {
      		"_version": "1.2.0",
      		"rootView": {
      			"viewName": "sithhorders.view.App",
      			"type": "XML",
      			"id": "app"
      		"dependencies": {
      			"minUI5Version": "1.36.0",
      			"libs": {
      				"sap.ui.core": {
      					"minVersion": "1.36.0"
      				"sap.m": {
      					"minVersion": "1.36.0"
      				"sap.suite.ui.microchart": {
      					"minVersion": "1.36.0"
      		"contentDensities": {
      			"compact": true,
      			"cozy": true
      		"models": {
      			"i18n": {
      				"type": "sap.ui.model.resource.ResourceModel",
      				"settings": {
      					"bundleName": "sithhorders.i18n.i18n"
      			"": {
      				"dataSource": "mainService",
      				"settings": {
      					"metadataUrlParams": {
      						"sap-documentation": "heading"
      					"useBatch": false
      		"routing": {
      			"config": {
      				"routerClass": "sap.m.routing.Router",
      				"viewType": "XML",
      				"viewPath": "sithhorders.view",
      				"controlId": "idAppControl",
      				"controlAggregation": "detailPages",
      				"bypassed": {
      					"target": [
      				"async": true
      			"routes": [
      					"pattern": "",
      					"name": "master",
      					"target": [
      					"pattern": "Orders/{objectId}",
      					"name": "object",
      					"target": [
      			"targets": {
      				"master": {
      					"viewName": "Master",
      					"viewLevel": 1,
      					"viewId": "master",
      					"controlAggregation": "masterPages"
      				"object": {
      					"viewName": "Detail",
      					"viewId": "detail",
      					"viewLevel": 2
      				"detailObjectNotFound": {
      					"viewName": "DetailObjectNotFound",
      					"viewId": "detailObjectNotFound"
      				"detailNoObjectsAvailable": {
      					"viewName": "DetailNoObjectsAvailable",
      					"viewId": "detailNoObjectsAvailable"
      				"notFound": {
      					"viewName": "NotFound",
      					"viewId": "notFound"
      		"resources": {
      			"js": []
      	"sap.platform.hcp": {
      		"uri": "webapp",
      		"_version": "1.1.0"
      Author's profile photo Charles Muriyadan
      Charles Muriyadan

      Thanks for your excellent blog!!

      On adding the code as per your blog, I get a warning as shown below. Will this cause any issue?


      Author's profile photo Mark Teichmann
      Mark Teichmann

      Hi Charles,


      it is only a warning and will not cause an issue. But from a coding perspective it would be nicer to write it like the following example:

      checkPromoFactSheetAvailable : function() {
          // By default: promo factsheet not available
          this._bPromoFactSheetAvailable = false;
          if (this._oCrossAppNav) {
              // Check if the intent for the promotion factsheet is supported
              var sIntent = "#Promotion-displayFactSheet";
              var oDeferred = this._oCrossAppNav.isIntentSupported([sIntent]);
              oDeferred.done(jQuery.proxy(function(oIntentSupported) {
                  if (oIntentSupported && oIntentSupported[sIntent] && oIntentSupported[sIntent].supported === true) {
                      // Remember that the navigation to the promotion factsheet is possible
                      this._bPromoFactSheetAvailable = true;
                      // Activate the promotion links if they were already added to the view
              }, this));


      Author's profile photo Charles Muriyadan
      Charles Muriyadan

      Thank you Mark!

      Author's profile photo Calvin Stauber
      Calvin Stauber

      now it is better to use “isNavigationSupported” instead of “isIntentSupported”.

      @deprecated switch to isNavigationSupported Note that this has a slightly different response



      Author's profile photo Sachin Rathod
      Sachin Rathod

      Hi Charles Muriyadan

      Did you solve the warning?

      If yes could you please post your code.

      Author's profile photo Mahesh Shegu
      Mahesh Shegu

      Hi Charles Muriyadan,

      Have you resolved the warning, if so can you please share the code. I am also facing same issue here.

      Author's profile photo Former Member
      Former Member

      Hi Mark thank you for the explanation.


      I am trying to use the same principles explained here to apply in SAP Portal.

      When I try to get the parameters from:

      var startupParams = this.getOwnerComponent().getComponentData().startupParameters;

      It says that I am trying to get the parameters from something that is undefined.

      Do you know if I have to define the routing in the Portal Manifest or the routing should be defined on the application that we want to read the parameters?

      I think that I can't access the arguments because in the Portal each time you navigate to a new page you initialize all the applications in that page again. So I don't think that the routing happens but only the oninit function.

      The thing is that I can actually navigate in the portal by using a similar implementation to what you explained above.

      If you could help me it would be great! Thank you!

      Author's profile photo Mark Teichmann
      Mark Teichmann

      Hi Jose,


      I do not use the SAP Portal but I think that routing is handled differently there. Maybe this help page will put you on track...

      Author's profile photo Former Member
      Former Member

      Hi Mark Teichmann

      Nice blog!! This helped a lot.
      But I can see in your screenshot  when clicking on the supplier in the orders app, the app not only navigates to the Suppliers app and opens up the detail but also the same Supplier is selected in the master list.

      I applied the same code but the order doesn't get selected in the master list. Can you share the code to implement the same.
      Also, when the updateFinished method is called, it calls the first item selected and replaces the same in the detail page.

      Kindly suggest a solution to the same.



      Author's profile photo Mark Teichmann
      Mark Teichmann
      Blog Post Author

      Hi Kanika,


      sorry for the late reply. We used the SAPUI5 Master-Detail Freestyle Application Template for the apps. It contains a ListSelector.js which takes care of the selection of master entry if I remember right.

      Author's profile photo Nagendran R
      Nagendran R

      Hi Mark,



      Can I get some values back to the calling application.





      Author's profile photo Mark Teichmann
      Mark Teichmann
      Blog Post Author

      when do you need values back in the calling application? Immediately when calling it or after you are finished in the called application and go back to the calling application?

      Author's profile photo Nagendran R
      Nagendran R

      Yes, Once I am finished and go back, I need to push some values to the calling application- may be some document number which I created.





      Author's profile photo Mark Teichmann
      Mark Teichmann
      Blog Post Author

      The route back from your called application to the calling application is just another cross-application navigation where you can also use startup parameters to push the values.

      Can't you use this mechanism to achieve what you would like to?

      Author's profile photo Nagendran R
      Nagendran R

      Hi Mark Teichmann 

      Thanks for your follow up.

      Will check and update on the issue.



      Author's profile photo Mudit Kumar
      Mudit Kumar


      ​Hi Mark,

      I have a similar requirement as you mentioned in your blog. I believe your application is doing Cross App navigation.

      My requirement is I want to create a reusable Module or an Application or a Library(whichever is possible to be consumed from Fiorri Launchpad). I want to create a Module which can be integrated or plugged in by any Consuming Application deployed on FLP.  I want to display the content of my module within the consuming application which is deployed in FLP.

      I tried to do it using it Library . I am able to access and use the Library from Consuming application from HCP. However I cant achieve this in FLP. When I run the consuming Application which internally uses my Library, it gives me some error.

      Can you suggest me some approach how to do it .

      Thanks for your help.

      Author's profile photo Former Member
      Former Member

      Thanks for you blog, the navigation is working as intended! However, it is not smooth yet:

      Once a target application is reached, it uses inner-app navigation to find the correct route to a view.

      So, if the app is reached via intend-based navigation,

      1. it starts in the default view (master).
      2. the master view starts loading
      3. onMasterMatched() is executed
      4. navigation to the correct view (detail) starts

      In case only the detail view will be displayed, loading the master view is unnecessary and causes flickering, like on a mobile device or when using the Worklist template.

      To prevent this unnecessary loading step, I would have to catch startup parameters before getRouter().initialize() in Component.js. But at that point I can not navigate.

      Is there any clean solution? I tried to naviagte at

      1. Router.attachBeforeRouteMatched in Component.js (not fired)
      2. onBeforeShow in the master view (still flickering)


      Author's profile photo Kai-Uwe Meiselbach
      Kai-Uwe Meiselbach

      Hi Jan,

      since 1.48, sap.ui.core.routing.Router.initialize(bIgnoreInitialHash?) provides the bIgnoreInitialHash parameter (see

      I leveraged this in the init() method inside the Component.js to decide if a startup parameter is provided and thus if the detail view or if the master view must be shown.

      Coding looks like this:

      1. Get the router (oRouter)
      2. Check if detail view must be shown:
        Check if startup parameters are provided and and if current hash equals empty string (inner app route must take precedence over startup parameters)
      3. If detail view must be shown:
        1. Use oRouter.initialize(true) to initialize the router but to NOT let it select and navigate to a view. Use oRouter.navTo() to navigate to the detail view.
        2. Else: Use oRouter.initialize() to initialize the router and let it select and navigate to the main view.

      Thus, main view is not loaded unnecessarily.

      Best regards,

      Author's profile photo Carlos Venturo
      Carlos Venturo

      Excelent post,


      Any chance to pass the parameters in some hidden way ? because to do it this mode , someone could alterer the url and see info not corresponding to the logged user.



      Author's profile photo Manohar R
      Manohar R

      Mark can you able to post the complete two application zip file