Skip to Content

In standard Fiori apps using Fiori elements the Share feature is available. This feature is also enabled by default if we use the List report Application template provided in Webide. It has two options (when there is no Jam integration) ‘Send Email’ and ‘Save as Tile’.

In this blog I will share my experience how we implemented it for a custom UI5 Application which uses XML views and Java Script controllers.

Getting it on user interface was the easy part. We added a button on the initial View which on press opens up a fragment with 2 options. We used a normal button sap.m.Button for ‘Send Email’ and AddBookmarkButton control from sap.ushell.ui.footerbar for ‘Save as Tile’ option.

<OverflowToolbar id="tool">
	<Button press="onPressShare" icon="sap-icon://action"/>
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core" xmlns:foot="sap.ushell.ui.footerbar">
	<Popover showHeader="false" placement="Bottom" >
		<VBox class="sapMPopoverCont">
			<Button text="Send Email" press="onPress" iconFirst="true" icon="sap-icon://email"/>
			<foot:AddBookmarkButton id="book" text="Save as Tile" title = "Maintenance Notification" showGroupSelection = "true"/>


onPress: function(oEvent) {
	sap.m.URLHelper.triggerEmail("", "Link to Maintenance Notification", window.location.href);


But for the functionality to work correctly we had to somehow persist the current app state so that when we click on the saved tile or the email link we see the same context.

How to do it ?

  1. Use Navigation Handler to store the inner app state. Our Application had a Smart Filter and a Smart table on the first view so that users can search for appropriate record/s. As soon as a filter criterion is entered and we search for entries we save the app state.
    onSearch: function(oEvent) {
    	var oTable = that.oView.byId("smartTable");
    	var oFilt = that.oView.byId("smartFilterBar");
    	var mInnerAppData = {
    		selectionVariant: oFilt.getDataSuiteFormat(),
    		tableVariantId: oTable.getCurrentVariantId()

Here we have selection variant which captures the filter which are set on screen and we save it in Inner App data.

On calling storeInnerAppState we will notice the URL will automatically change and a parameter will be added similar to this –


Note : We will have to define the navigation handler in the controller to use it. 

  1. Add a new Route in manifest file to accommodate handing of URLs with parameter “sap-iapp-state” –
    "routes": [
            "pattern": "",
            "name": "notificationList",
            "target": "notificationList"
            "pattern": ":?sap-iapp-state:",
            "name": "notifListQuery",
            "target": "notificationList"
    "targets": {
    		"notificationList": {
    			"viewPath": "XXXXX.view",
    			"viewName": "NotificationList",
    			"viewLevel": 1

   If this is not done we will get an error because the first view has no pattern attached to it –

  1. Add a new data source in manifest and point it to standard Odata service INTEROP where the internal app data is stored –


  1. Add a model with any name, (we used the name GlobalContainers) so that we can make an Odata call to fetch the stored context. 


  1. Finally in the init method of the initial view we incorporate logic to read the app state id and set the saved app data before the first view is loaded. for doing this we parse the app state id from the URL and pass it to the global oData service to retrieve the saved app data. Then we set the appropriate view elements.
    onInit: function() {
    	var controller = this;
    	this.oNavigationHandler = new NavigationHandler(this);
    	that = this;
    	var oView = this.getView();
    	var appStateKey = "";
    	var url = window.location.href;
    	var i ='sap-iapp-state');
    	if (i > 0) {
    		i = i + 15;
    		appStateKey = url.substring(i);
    	if (appStateKey) {
    		var url1 = "/GlobalContainers('" + appStateKey + "')";
    		var oModel = this.getOwnerComponent().getModel('GlobalContainers');
    		var that1 = this;
    		var functionSucess = function(oData, controller) {
    			var oFilt = that1.getView().byId("smartFilterBar");
    			var obj = JSON.parse(oData.value);
    			oFilt.setDataSuiteFormat(JSON.stringify(obj.selectionVariant), true);
    		var functionError = function(oError) {
    			var test = oError;
    		var params = {
    			success: function(oData, controller) {
    				functionSucess(oData, controller);
    			error: function(oError) {
 , params);


Regards, Saurabh

To report this post you need to login first.


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

  1. Former Member

    Hi Saurabh,

    Very nice blog.

    I have one query here. In point 3, you have specified that we require an Odata service INTEROP where the internal app data is stored. Is this service also available in the fiori launchpad provided in cloud foundary?

    1. Saurabh Sharma Post author

      Thank you Anubha,

      I have tried this standard service with the on premise back end. If you deploy the your apps on launchpad which is on SAP cloud (Portal service) it will work because the your app is still pulling data from SAP back end only. You would have to use cloud connector to connect to back end though. If we are talking about SAP public cloud, I would guess it should work but I did not get a chance to test it till now. Maybe you an try it out and share your experience.



    1. Saurabh Sharma Post author

      Hey Soumya,

      That was the first thing that I tried but it did not work out. I wanted to build the share option which is available by default in applications which are built using the smart templates provided by SAP Webide and also apps using the fiori 2.0 controls(like list report and object pages) in a traditional UI5 app. This blog lists down the steps I followed for implementation.


      Saurabh Sharma


Leave a Reply