Skip to Content
Author's profile photo Saurabh Sharma

How to enable the share option and persist current application state in a UI5 application

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">
	<ToolbarSpacer/>
	<Button press="onPressShare" icon="sap-icon://action"/>
</OverflowToolbar>
<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"/>
		</VBox>
	</Popover>
</core:FragmentDefinition>

 

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()
    	};
    
    	that.oNavigationHandler.storeInnerAppState(mInnerAppData);
    
    }​

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 –

?sap-iapp-state=ASFLPLTWYA4IFMGQ1CG58TQG5SFZNXJYHI4QANW8

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 = url.search('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) {
    			sap.ui.core.BusyIndicator.hide();
    			var oFilt = that1.getView().byId("smartFilterBar");
    			var obj = JSON.parse(oData.value);
    			oFilt.setDataSuiteFormat(JSON.stringify(obj.selectionVariant), true);
    		}
    
    		var functionError = function(oError) {
    			sap.ui.core.BusyIndicator.hide();
    			var test = oError;
    		}
    
    		sap.ui.core.BusyIndicator.show();
    		var params = {
    			success: function(oData, controller) {
    				functionSucess(oData, controller);
    			},
    			error: function(oError) {
    				functionError(oError);
    			}
    		};
    
    		oModel.read(url1, params);
    	}
    }​

 

Regards, Saurabh

Assigned tags

      11 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Former Member
      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?

      Author's profile photo Saurabh Sharma
      Saurabh Sharma
      Blog 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.

      Regards,

      Saurabh

      Author's profile photo Alexander Parr
      Alexander Parr

      Hey,
      I can confirm that needed Firoi Launchpad Services are provided in an scenario without ERP Backend connection too!

      Best
      Alex

      Author's profile photo Soumyadeep Dasgupta
      Soumyadeep Dasgupta

      Hi Saurabh,

       

      Is this the only way, what about showCreateTile option of Variant control.  Have you tried that? For me it is showing Create as tile option in 'Save As' dialog , but it is not creating tile.

      https://experience.sap.com/fiori-design-web/variant-management/#create-as-tile

       

       

       

      Author's profile photo Saurabh Sharma
      Saurabh Sharma
      Blog 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.

      Regards,

      Saurabh Sharma

      Author's profile photo Anmol Goel
      Anmol Goel

      Hi Saurabh,

      Do you know for how long does it persist the app state in the table?

      Regards,

      Anmol

      Author's profile photo Saurabh Sharma
      Saurabh Sharma
      Blog Post Author

      Forever I guess or till you don't copy the system data from a different environment.

      Author's profile photo Thomas Mundt
      Thomas Mundt

      Dear Saurabh,

      Thank you for this guiding approach to handle app state on UI5!
      Can you say if using the uishell service “CrossApplicationNavigation” can do the same as “NavigationHandler”?

      I figured out that invoking methods on “CrossApplicationNavigation” generates AppState object (and its key), but does not seem to persist anything. I think I should see any data being persisted, right?

      Any tipps or comments are welcome! ?

      Yours, Thomas

      Author's profile photo Alexander Parr
      Alexander Parr

      Hi,
      I think under the hood NavigationHandler is making use of  the ‘CrossApplicationNavigation’ Service. When I was trying to implement state handling for our apps, I faced the situation that save methods are not saving the context to any service and when we tried to retrieve any context, we got HTTP status code 403 – forbidden.

      Solution: Turn on option ‘Save App State Data’ under Fiori Launchpad Administrator Page -> Settings -> System Settings.

      After that, app states are working as expected!

       

      Saurabh Sharma This might be worth an update of your post?

      Author's profile photo Thomas Mundt
      Thomas Mundt

      Hi Alexander,

      Thank you for your reply.

      In our app, I use "CrossApplicationNavigation" service and its method "createEmptyAppState" to store the app's state via its component.

      And that was the solution for me, I did not need to turn any options on in the FLP anyways.

      It is great to use this ushell service to persist state in an Fiori App and to create/use a tile for persisting/re-initialization.

       

      Author's profile photo Jayakrishnan Chandramohan
      Jayakrishnan Chandramohan

      Hi  Saurabh Sharma Thanks for your blog.. i followed the same blog as well.  I created add Bookmark Button and placed the same logic.

      When i run my app in flp sandbox, i can create the the tile by pressing the add Bookmark button. Tile successfully created

      But when i open the newly created tile in my flp, it run as the same original app. It does not brings out the saved data on the filter bars.

      When i do the debug, i see the  below oModel does not contain any data inside it.

      var oModel = this.getOwnerComponent().getModel('GlobalContainers');

      Doo you have any ide regarding this? i suspect the tile i created did not store any data in side the GlobalContainers model?

      Or something related  to sandbox server?

      Thanks ,

      Regards,

      Jayakrishnan.C