Skip to Content
Technical Articles
Author's profile photo Ashish Anand

Overview page (OVP) developer extension

As part of this blog series, we have already learned about how to configure different cards for an overview page. In this blog, I’ll discuss how an application developer can extend the standard overview page to cater to some of the custom needs. OVP has provided different extension point (breakout) which we will be discussing in detail.

Custom global actions

OVP provides a “share” button by default on the top level of smart filter bar. If you want to add some global action buttons to it, please follow the following steps:

  1. Right click on the project –> New –> Extension
  2. In Template selection pop up, select Overview page extension
  3. in extension setting pop up, choose “Global Actions” and click next

After completing the above three steps, the Web-IDE extension wizard has done following things for you in the background:

  1. Created custom.controller.js and customAction.fragment.xml file under web-app –> ext folder of your project
  2. Updated the manifest.json file to add the newly created controller and view extension.
    "extends": {
    			"extensions": {
    				"sap.ui.controllerExtensions": {
    					"sap.ovp.app.Main": {
    						"controllerName": "demo.ovp.BusinessOverview.ext.custom"
    					}
    				},
    				"sap.ui.viewExtensions": {
    					"sap.ovp.app.Main": {
    						"SmartFilterBarGlobalActionExtension": {
    							"className": "sap.ui.core.Fragment",
    							"fragmentName": "demo.ovp.BusinessOverview.ext.customAction",
    							"type": "XML"
    						}
    					}
    				}
    			}
    		},​

in customAction.fragment.xml file, you can add any number of sap.m.button control and it will appear as custom global action buttons in your OVP application.

<core:FragmentDefinition xmlns="sap.m" xmlns:smartfilterbar="sap.ui.comp.smartfilterbar" xmlns:core="sap.ui.core">
	<Button text="Action1" press="handleCustomAction" type="Transparent"></Button>
	<Button text="Action2" press="handleCustomAction" type="Transparent"></Button>
</core:FragmentDefinition>

in custom.controller.js file you can define event handlers for the “press” event of your custom buttons

handleCustomAction: function () {
				var msg = 'Custom Global Action clicked';
	            MessageToast.show(msg);
		}

Custom Filter

Apart from the attributes of the globalFilterEntityType, the application developer can add some custom filter fields to the smart filter bar of OVP application via the following steps:

  1. Follow Step 1 and 2 as similar for “Custom global filters” (mentioned in the above section)
  2. in step 3, select “Filter” instead of “Global Actions”

After completing the above three steps, the Web-IDE extension wizard has done following things for you in the background:

  1. Created customFilter.fragment.xml file under web-app –> ext folder of your project
  2. Updated the manifest.json file to add the newly created controller and view extension.
    "SmartFilterBarControlConfigurationExtension|GlobalFilters": {
    							"className": "sap.ui.core.Fragment",
    							"fragmentName": "demo.ovp.BusinessOverview.ext.customFilter",
    							"type": "XML"
    						}​

You can define any number of custom filter field in the customFilter.fragment.xml file.

Also, you need to override the following method in your custom.controller.js file to make these custom filters work in sync with your OVP application:

getCustomFilters()

This method returns a filter (sap.ui.model.Filter) to the main OVP application, this custom filter will get added to the standard filters of the OVP application. If we have defined more than one custom filter, then all the filters should be clubbed and returned as one filter.

getCustomFilters: function () {
			var oValue1 = this.oView.byId("ProductID").getValue();
			var oValue2 = this.oView.byId("SalesOrderID").getValue();

			var aFilters = [],
				oFilter1, oFilter2;

			if (oValue1) {
				oFilter1 = new Filter({
					path: "ProductID",
					operator: "EQ",
					value1: oValue1
				});
				aFilters.push(oFilter1);
			}

			if (oValue2) {
				oFilter2 = new Filter({
					path: "SalesOrderID",
					operator: "EQ",
					value1: oValue2
				});
				aFilters.push(oFilter2);
			}

			if (aFilters && aFilters.length > 0) {
				return (new Filter(aFilters, true));
			}
		},

This method can also be very useful when we need to set the filter for two different unrelated propeties.

getCustomAppStateDataExtension(oCustomData)

This method returns custom filter data so that app-state can be formed out of it.

getCustomAppStateDataExtension: function (oCustomData) {
			var oCustomField1 = this.oView.byId("ProductID");
            var oCustomField2 = this.oView.byId("SalesOrderID");
            if (oCustomField1) {
                oCustomData.ProductID = oCustomField1.getValue();
            }
            if (oCustomField2) {
                oCustomData.SalesOrderID = oCustomField2.getValue();
            }
            return oCustomData;
		},

restoreCustomAppStateDataExtension(oCustomData)

This method restores the custom filter data.

restoreCustomAppStateDataExtension: function (oCustomData) {
			var oCustomField1 = this.oView.byId("ProductID");
			oCustomField1.setValue();

			var oCustomField2 = this.oView.byId("SalesOrderID");
			oCustomField2.setValue();

			if (oCustomData) {

				if (oCustomData.ProductID) {
					oCustomField1.setValue(oCustomData.ProductID);
				}

				if (oCustomData.SalesOrderID) {
					oCustomField2.setValue(oCustomData.SalesOrderID);
				}
			}
		},

modifyStartupExtension(oCustomSelectionVariant)

This method can be used to set the initial value of the filters dynamically.

modifyStartupExtension: function (oCustomSelectionVariant) {
			oCustomSelectionVariant.addSelectOption("SupplierName", "I", "EQ", "Talpa");
		},

Custom Navigation params

In order to add some custom navigation parameters on intent based navigation for a card, we need to follow the following steps:

  1. add card setting “customParams” to the card
    "card01": {
    				"model": "GWSAMPLE_BASIC",
    				"template": "sap.ovp.cards.list",
    				"settings": {
    					"title": "{{card01_title}}",
    					"subTitle": "Standard List card - Standard flavour",
    					"entitySet": "ProductSet",
    					"listType": "condensed",
    					"listFlavor": "standard",
    					"sortBy": "Availability_Status",
    					"sortOrder": "Descending",
    					"annotationPath": "com.sap.vocabularies.UI.v1.LineItem",
    					"identificationAnnotationPath": "com.sap.vocabularies.UI.v1.Identification#productHeader1",
    					"addODataSelect": true,
    					"stopResizing": false,
    					"customParams" "getParameters",
    					"defaultSpan": {
    						"rows": 5,
    						"cols": 1,
    						"showOnlyHeader": false
    					}
    				}
    			}​
  2. Override method onCustomParams in your custom.controller.js file. This method returns a function.
    getParameters: function(oNavigateParams,oSelectionVariantParams) {
                var aCustomSelectionVariant = [];
                var aSelectOptions = oSelectionVariantParams.getSelectOptionsPropertyNames();
                if(aSelectOptions.indexOf("SupplierName")!=-1) {
                    var aSupplierFilter = oSelectionVariantParams.getSelectOption("SupplierName");
                    var sSupplierFilterValue = aSupplierFilter[0].Low;
                    aSupplierFilter[0].Low = "";
                }
                var oSupplierName = {
                  path: "SupplierName",
                    operator: "EQ",
                    value1: "",
                    value2: null,
                    sign: "I"
                };
                var oLandFilter = {
                  path: "Land1",
                    operator: "EQ",
                    value1: sSupplierFilterValue,
                    value2: null,
                    sign: "I"
                };
                var oCustomSelectionVariant = {
                    path: "TaxTarifCode",
                    operator: "EQ",
                    value1: 5,
                    value2: null,
                    sign: "I"
                };
                aCustomSelectionVariant.push(oCustomSelectionVariant);
                aCustomSelectionVariant.push(oLandFilter);
                aCustomSelectionVariant.push(oSupplierName);
                return {
                    selectionVariant: aCustomSelectionVariant,
                    ignoreEmptyString: true
                };
            },
    		
    		onCustomParams: function (sCustomParams) {
    			if (sCustomParams === "getParameters") {
    	                return this.getParameters;
    	            } else if (sCustomParams === "param2") {
    	                return this.param2;
    	            }
    		},​

    As you must have noticed in the above example, the onCustomParams method returns function fo signature:

    • Input parameters:
      1.  oContextData: This contains information (property, value pairs) about the current context, Eg, if a list line item is clicked, then it carries info about that line.
      2. oSelectionData (optional): This contains information on card filters and Global filters. We can also manipulate existing selection variant of the card.
    • Return Type: An object with the following attributes:
      1.  aSelectionVariant: An array of objects containing custom parameters. Each object should have properties path, operator, value1, value2 and sign.
      2.  bIgnoreEmptyString :  a flag whether to ignore empty string in navigation parameters/selection variant.
        the ignoreEmptyString flag will remove all the parameters/selection variant coming from the global filter, card level filters and custom filters

Custom Navigation target

This navigation is used to allow the developer to have different navigation behaviour from different areas of the card.  In order to achieve this method “doCustomNavigation” method in your custom.controller.js.

/************************* Handler for custom navigation ************************************************
		 
		 * This function takes the standard navigation entry details (if present) for a particular card and context
		 * and return a new/modified custom navigation entry to the core. The core will then use the custom
		 * navigation entry to perform navigation
		 * @param sCardId  : Card id as defined in manifest for a card
		 * @param oContext : Context of line item that is clicked (empty for header click)
		 * @param oNavigationEntry : Custom navigation entry to be used for navigation
		 * @returns {object} : Properties are {type, semanticObject, action, url, label}
		 * @public
		 **/

		doCustomNavigation: function (sCardId, oContext, oNavigationEntry) {
			var oCustomNavigationEntry;
		    var oEntity = oContext && oContext.sPath && oContext.getProperty && oContext.getProperty(oContext.sPath);
		    if (sCardId === "card001" && oEntity && oEntity.PurchaseOrder === "4500003575") {
		        oCustomNavigationEntry = {};
		        oCustomNavigationEntry.type = "com.sap.vocabularies.UI.v1.DataFieldForIntentBasedNavigation";
		        oCustomNavigationEntry.semanticObject = "Action";
		        oCustomNavigationEntry.action = "toappnavsample";
		        oCustomNavigationEntry.url = ""; //Only required when type is DataFieldWithUrl
		        oCustomNavigationEntry.label = ""; //Optional
		    }
		    return oCustomNavigationEntry;

		},

Custom Action for stack card

We have already discussed that stack card can have some action button at the footer area. It is also possible for the application developer to add custom buttons by following the below steps:

  1. add the property “customAction” to the card settings of the stack card
    "card9": {
    				"model": "GWSAMPLE_BASIC",
    				"template": "sap.ovp.cards.stack",
    				"settings": {
    					"title": "{{card9_title}}",
    					"entitySet": "SalesOrderSet",
    					"subTitle": "Open orders to approve",
    					"addODataSelect": false,
    					"objectStreamCardsSettings": {
    						"annotationPath": "com.sap.vocabularies.UI.v1.Facets#stack",
    						"customActions": [{
    							"text": "action 1",
    							"press": "press1",
    							"position": 1
    						}, {
    							"text": "action 2 ",
    							"press": "press1",
    							"position": 5
    						} {
    							"text": "action 3",
    							"press": "press1",
    							"position": 10
    						} {
    							"text": "action 4",
    							"press": "press1",
    							"position": 20
    						}]
    					},
    					"identificationAnnotationPath": "com.sap.vocabularies.UI.v1.Identification#header,com.sap.vocabularies.UI.v1.Identification#card"
    				}
    			}​
  2. override method onCustomActionPress in your custom.controller.js. this method accepts one argument i.e. value defined in “press” property of customAction card setting. This method should return another event handler method for the press of the custom action button.
    onCustomActionPress: function (sCustomAction) {
    				if (sCustomAction === "press1") {
    		                return this.press1;
    		            } else if (sCustomAction === "press2") {
    		                return this.press2;
    		            }
    		},
    		
    		press1: function(oEvent) {
    		            window.open("https://www.google.co.in");
    		        },
    		
    		        press2: function(oEvent) {
    		            window.open("http://www.sap.com/index.html");
    		        },​

Custom Cards

OVP framework also allows the application developer to define their own card type and use them in their OVP application. I’ll discuss this in my next blog of this blog series.

Assigned Tags

      24 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Pawan Kalyan K
      Pawan Kalyan K

      Hello Ashish Anand

      Thanks for the nice blog. Can you please let me know is it possible to extend Procurement OverView App or not . Because , when I am trying to extend the app through WebIDe , I am getting a message "There must be atleast one XML View matching with its controllers "

       

      How to extend this Procurement OverView App?

      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      Hi ,

       

      as of now its not possible to extend the shipped apps via web ide. Only app developer  who is developing the application using OVP library can use extensions provided by OVP to do some customisation

       

      thanks and regards

      ashish

       

      Author's profile photo Pawan Kalyan K
      Pawan Kalyan K
      Hello Ashish Anand,
      Thanks for the reply . But one strange thing which i couldn't understand is,  On CLick of Card , It is navigating to another application through UI Identificatin -> Data Field for Intent Based Navigation.
      I am seeing clearly Semantic Object & Action of the new application as well. So I am just trying to configure my New Custom App for this Semantic Object Action Pair in my system. Still from the Card of Procurement overview App, I am not able to launch my custom app...
      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      Hi Pawan Kalyan ,

      Are you getting any error? It should navigate to the application which properly mentioned semantic object and action.

      Thanks and Regards

      Ashish

      Author's profile photo Pawan Kalyan K
      Pawan Kalyan K

      Hi Ashish Anand ,

      Thanks for the reply . Actually on click of card, it is navigating to new app through semantic object and action pair.

       

      I created in system with the same set of semantic object and action pair ,different app .But it is always navigating to the original app but not to the app which i configured .

       

      Eventhough i configured with identical semantic object and action combination. Later ,I tried to change the standard catalog semantic object and action pair and on click of card , it is now navigating to the app which i wanted.

      Not sure , why and how SAP is preferring the standard catalog semantic object and action pair even though customer has a different app configured for the same Intent. 

       

       

       

      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      Hi pawan,

      im not much of an expert on FLP configuration but as per my understanding  every application should have unique pair semantic object and action.

      Why don’t you give your custom application an unique intend and configure the same in your OVP navigation.

      This should work. Best of luck

      thanks and regards

      ashish

       

      Author's profile photo Atul Sharma
      Atul Sharma

      Hi Ashish ,

      Thanks for the detailed info .:)

      it is helpful .

      Regards ,

      Atul .

      Author's profile photo Kimi Xu
      Kimi Xu

      Hi Ashish,

       

      thanks for your blog, where we could find useful resources about OVP extensibility.

      I have a question regarding the OVP smart-filterbar.

      Is there any possibility for user to set property for this smartfilterbar:

      • for example the property useDateRangeType="true", is the one I need for making some changes for date-picker input.

       

      Best regards,

      Kimi Xu

      Author's profile photo Akshaya Parthasarathy
      Akshaya Parthasarathy

      can we pass parameters to datafieldwithurl in

      doCustomNavigation
      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      Hi akshaya parthasarathy ,

      No passing / altering parameters with this breakout is not supported. However it takes all the standard and custom parameters of the card by default. And in case of DataFiledWithURL you can try adding parameters in your URL itself.

      Thanks and Regards

      Ashish

      Author's profile photo Akshaya Parthasarathy
      Akshaya Parthasarathy

      Hi Ashish Anand

      Can we configure to open in a new tab in the docustomnavigation method?

      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      Hi akshaya parthasarathy ,

      Anything which the end user clicks with (CRTL + Click) is opened in new tab by default in OVP. application developer need not configure anything for this.

      Thanks and Regards

      Ashish

      Author's profile photo Akshaya Parthasarathy
      Akshaya Parthasarathy

      thanks

      Author's profile photo Jitin Khanna
      Jitin Khanna

      Hi Ashish,

      What would be the procedure to bring Display Currency Global Filter in Procurement Overview Page?

      We are trying to create a new Procurement Overview page by using Standard OData service of Original Procurement OVP.

      Should we consider the approach of creating a copy of standard Procurement Overview page and extend the Smart filter with Global Display Currency?

      Appreciate your quick response.

       

      Thanks

      Jitin

      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      Hi Jitin,

      If extending the Smart filter with Global Display Currency is the only requirement then this approach looks good to me.

      Thanks and Regards

      Ashish

      Author's profile photo Akshaya Parthasarathy
      Akshaya Parthasarathy

      Hi Ashish Anand

      I have configured datafieldforintentbased navigation in line items of my list card. and I'm sending custom parameters through get parameteers method. however the method doesnt get invoked when I click on the line item. If i do the same action after clicking the header once, it gets invoked. Can you help on why is that happening?

      Author's profile photo Urvish Vijay Panchal
      Urvish Vijay Panchal

      Hi Ashish Anand,

      I am using OVP extension in one of my project. Facing following issue in onCustomParams() mentioned in below link.

      https://stackoverflow.com/questions/57093342/maintain-flow-in-function-executions-in-sap-ui5

      https://answers.sap.com/questions/12736199/maintain-flow-in-function-executions-in-sap-ui5.html

      regards,

      Urvish

      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      Hello Vijay,

      These extensions are meant not to be used in an asynchronous way. Only extension you can use in OVP in an asynchronous way is modifyStartUpParameters. You can fetch the backend values via this extension at app startup and use them later on in other extensions.

      Hope it helps 🙂

      Thanks and Regards

      Ashish

      Author's profile photo Hian Joy
      Hian Joy

      Hi Ashish Anand,

      Thanks for such a wonderful blog.

      I have created Analytical card and I want to navigate/ pass params depending upon what bar of my graph has user selected. Basically I have grouped the Bar on status and on selecting bar of particular status he should see the list(another app) filtered based on status.

      Could you pls guide on this

      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      Hi Hiran,

      I think you just configure the intend based navigation and the status of the bar clicked should be passed automatically to the target application.

      Thanks and Regards

      Ashish

      Author's profile photo Hian Joy
      Hian Joy

      Thanks Ashish,

      I worked but was a bit tricky, had to include the parameter in the Intent config and also handling it on the other side through onInitSmartFilterBarExtension  and using navigation handler promise function.

      Author's profile photo Ashish Anand
      Ashish Anand
      Blog Post Author

      hmm, Happy it worked out for you 🙂

      Author's profile photo shinynickitha chellam
      shinynickitha chellam

      Hi Ashish Anand

      I have mandatory filters in my application. I dont pass any default value to it. "enableLiveFilter" property is set to false.

      When I load the application, I see the filters are marked red.

      Any help?

      I tried to get the control ByKey and set the value state of it to "None". But that doesnt help!

      Could you please help?

       

      Thanks,

      Shiny

       

      Author's profile photo Abhishek Nayak
      Abhishek Nayak

      Hello Ashish,

       

      I have similar requirement, that I need to add Date field as selection criteria.

      Only thing is , I have created OVP application using CDS. Now I have added a parameter to my consumption CDS view. And I need to pass value to that parameter from the field added using OData extension.

      Can you please help