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">
	<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

To report this post you need to login first.

1 Comment

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

  1. Anubha Jain

    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?

    (0) 

Leave a Reply