SAP Fiori, NW ABAP Gateway (OData), SAP S/4HANA, SAPUI5, SAP ABAP CDS

10 Interesting hacks for UI5 apps using Fiori Elements (Object Page and List Report Floorplans)

Hope you all are enjoying the S/4HANA landscape and stretching the boundaries of the new dictionary objects – ABAP CDS and AMDP. In this blog I will share some of the techniques that I have learned while using Fiori Elements over the last few years.

The Backend as usual consists of ABAP CDS views which I have referenced in a oData service(SEGW). This gives me the flexibility to have all the CRUD operations at one place and also to put some oData annotations in MPC. Let’s concentrate on the Frontend side for now which is the focus of this blog.

1.Master data lock Using annotations

This is relevant to transnational apps. In list report some of the records could be editable while others are not (say based on a status or authorization). One way of handling updates is through the backend API at the time of save and display appropriate error message on the app. But a better way is to use the capability annotations to associate the editable property to a field. See the source code. Please note these annotations are at the entity set level.

<Annotations Target="ZCUSTOMORDER_SRV.ZCUSTOMORDER_SRV_Entities/zcustom_order">
	<Annotation Term="Capabilities.UpdateRestrictions">
		<Record Type="Capabilities.UpdateRestrictionsType">
			<PropertyValue Property="Updatable" Path="phas0"/>
		</Record>
	</Annotation>
	<Annotation Term="Capabilities.DeleteRestrictions">
		<Record Type="Capabilities.DeleteRestrictionsType">
			<PropertyValue Property="Deletable" Path="phas0"/>
		</Record>
	</Annotation>
</Annotations>

2. Automatic value help for Filters and Object Page fields

If we need to use value help popup (associated with each editable field) we have to press the “Go” button each time. It also slows down a user if they want to do the data entry in the app quickly. One option was to use drop downs but then we loose the ability to enter filter criterion. The solution is to use the “configuration” aggregation for smart fields and “controlConfiguration” aggregation for smart filter fields. The id of the controls for apps that use Fiori elements can be quite big as you will notice.

//Auto value help logic for Smart Filter 
var smFilt = this.getView().byId(
    "zcustomorder::sap.suite.ui.generic.template.ListReport.view.ListReport::zcustom_order--listReportFilter");
var conConfig = smFilt.getControlConfiguration();
conConfig.forEach(function(item, idx, arr){
	smFilt.removeControlConfiguration(item);
	item.setPreventInitialDataFetchInValueHelpDialog(false);
	smFilt.addControlConfiguration(item);
}, this);
//Automatic value help for Object Page smart field
var fld = this.oView.byId("zcustomorder::sap.suite.ui.generic.template.ObjectPage.view.Details::zcustom_order--RF1::qmnum::Field");
if (fld) {
	var oConfig = fld.getConfiguration();
	if (!oConfig) {
		oConfig = new sap.ui.comp.smartfield.Configuration();
	}
	oConfig.setPreventInitialDataFetchInValueHelpDialog(false);
	oConfig.setDisplayBehaviour(sap.ui.comp.smartfield.DisplayBehaviour.descriptionAndId);
	fld.setConfiguration(oConfig);
}

3. Charts as a tab in list report

This is a comparatively new feature(available only UI5 library version 1.60 onward). How to get multiple tabs in list report using Selection Variants.

The trick for charts is to use a Presentation variant instead (or a selectionPresentation variant). One problem I faced while implementing this approach was that I had to explicitly load the Chart entity set(in list report onInit() method ) as it does not load automatically.

Read More: SAP Fiori Application Developer Certification

onInit: function(){
      //Somehow the chart entity is not called automatically so we need to call it explicitly to load
      this._loadChart();
},

_loadChart: function(){
	var url = "/zcustom_order_chart";
	var oModel = this.getOwnerComponent().getModel();
	var params = {
		async: false,
		success: function (oData, controller) {
			//Do nothing. The Smart chart will automatically read it. 
			sap.ui.core.BusyIndicator.hide();
		},
		error: function (oError) {
			sap.ui.core.BusyIndicator.hide();
		}
	};
	oModel.read(url, params);
}

4. Navigation to external apps passing parameters and preferred mode.

This was a requirement for me for some time specially to pass parameters. The trick here is to set the inbound parameters in the manifest file of the target app.

5. Dynamic default filters(Static default values are already supported through annotations)

We can set Dynamic values as default filter values using the method setDataSuiteFormat() of the smart filter bar. Check out the onAfterRendering method of ListReportExt.controller.js file. This is convenient since we can set only static or hardcoded values using annotations as of now(Look for @Consumption.filter.defaultValue in the CDS view zcustom_order at the end)

onAfterRendering: function () {
	// Current timestamp set as default filter for order start but this way we can set any field dynamically
	var smFilt = this.getView().byId(
		"zcustomorder::sap.suite.ui.generic.template.ListReport.view.ListReport::zcustom_order--listReportFilter"
	);
	var dat = new Date();//Java script date object
	var datStr = dat.toISOString(); // Convert it to format that SAP understands
	var jsonString =
		'{"SelectionVariantID":"","Parameters":[{"PropertyName":"orderstart","PropertyValue":"' + datStr +'"}]}';
	smFilt.setDataSuiteFormat(jsonString);
}

6. Enhancing a standard framework button

It’s a common requirement to enhance a standard SAP framework button. There could be a few reasons for that like controlling the edit or display behaviour of fragment built as part of object page section extension. The best way to proceed with this is to attach a press event to the button and write the logic in the function call back.

Read More: SAP ABAP 7.5 Certification

onAfterRendering: function () {
	this._oEditButton = this.getView().byId(
		"zcustomorder::sap.suite.ui.generic.template.ObjectPage.view.Details::zcustom_order--edit");
	this._oEditButton.attachPress(this.onEditPress);
},
	
onEditPress : function(){
	sap.m.MessageToast.show("Edit button pressed");
},

7. Enhancing a smart field with hyperlink.

This is like enhancing the Standard button. We could potentially do this with annotations like UI.fieldGroup.type. Check the CDS annotation documentation for more details. But the annotation approach is too restrictive. We can alternatively attach a press event to the smart field and handle it in the controller. This way we can pass multiple parameters and preferredMode to the target app.

onNotifPress : function(){
var sPath = that.getView().getBindingContext().getPath();
var notifNo = that.getView().getModel().getProperty(sPath + “/qmnum”);
var oNavControl = that.extensionAPI.getNavigationController();
oNavControl.navigateExternal(“Notification”, {
qmnum: notifNo
});
}

8. Filter facet –

This is another cool local annotation. When reusing the CDS views for value help the UI.Fieldgroup qualifiers make the screen look very cluttered. See the screen shot.

The solution is to use the Filter Facet which removes all the unnecessary grouping in filter.Check out the annotation file at the end.

9. Add reference to custom library and test inter-app navigation in webide testing without deployment to front end server.

Now it is even simpler with SAP template in WEBIDE.

This way you can refer to your custom libraries in workspace or Frontend server and still test the app in WEBIDE itself.

Only thing you need to be careful about is maintaining the Inbound Semantic Object and Action in manifest. If you are going to deploy to Frontend server maintain the same in /UI2/SEMOBJ transaction.Lastly run FLPSandbox app instead of your own app to test it.

10. Using Internet APIs like Google charts

In this last item I want to touch upon the use of internet APIs. I faced a lot of issues with this in past because if I want to use some internet APIs and deploy the app on Fiori Launchpad of Frontend server I get CORS(Cross Origin Resource Sharing) issues. You can find loads of information about that on internet.

Earlier I was using the “registerModulePath” and “require” which works in WEBIDE but fail to load the APIs when the app is deployed on Frontend server.

jQuery.sap.registerModulePath("google", "https://www.gstatic.com/charts/loader");
jQuery.sap.require("google");

The new method I discovered which works without issue in our On-Premise Frontend server is includeScript –

jQuery.sap.includeScript("https://www.gstatic.com/charts/loader.js", "NewId", function () {  
        google.charts.load('current', {'packages': ['gauge']});
      // Put rest of the logic to build the chart
});

Application Demo

Putting it all together –

Custom Order CDS View

@AbapCatalog.sqlViewName: 'ZCUSTORD'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Custom Order'

@ObjectModel.createEnabled: true
@ObjectModel.deleteEnabled: true
@ObjectModel.updateEnabled: true

define view zcustom_order
  as select from zcustomorder
  association [* ] to zcustom_notif as _NotifHelp on _NotifHelp.qmnum = zcustomorder.qmnum
{

      @UI : {
        lineItem: [{ position: 10 }],
        selectionField: [{ position: 10 }],
        fieldGroup: [{
                  qualifier: 'Header1',
                  position : 10
              },
              {
                  qualifier: 'Overview1',
                  position : 10
              }]
      }      
  key aufnr,
      @UI : {
       lineItem: { position: 20 },
       selectionField: { position: 20 },
       fieldGroup: {
                 qualifier: 'Overview1',
                 position : 20
             }
      }
      ktext,
      @UI : {
      lineItem: [{ position: 30 }],
      selectionField: [{ position: 30 }],
      fieldGroup: {
             qualifier: 'Overview2',
             position : 10
         }
      }
      auart,
      @UI : {
      lineItem: [{ position: 40 }],
      selectionField: [{ position: 40 }],
      fieldGroup: {
             qualifier: 'Overview2',
             position : 20
         }
      }
      @Consumption.filter.defaultValue: '30'
      auftyp,
      @UI : {
      lineItem: [{ position: 50 }],
      selectionField: [{ position: 50 }],
      fieldGroup: {
             qualifier: 'Overview3',
             position : 10
         }
      }
      werks,
      @UI : {
      lineItem: [{ position: 60 }],
      selectionField: [{ position: 60 }],
      fieldGroup: {
             qualifier: 'Overview4',
             position : 20
         }
      }
      phas0,
      @UI : {
      lineItem: [{ position: 10 }],
      selectionField: { position: 70 },
      fieldGroup: {
             qualifier: 'Overview4',
             position : 10
         }

      }
      @Consumption.valueHelp: '_NotifHelp'
      qmnum,
      @UI : {
      lineItem: [{ position: 10 }],
      selectionField: { position: 80 },
      fieldGroup: {
             qualifier: 'Overview3',
             position : 20
         }
      }
      @Consumption.filter: {selectionType : #SINGLE, multipleSelections: false}
      @EndUserText.label: 'Order Start Date'
      orderstart,
      
      _NotifHelp
}

Chart CDS View –

@AbapCatalog.sqlViewName: 'ZCUSTORDCHART'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Custom order chart'
@UI.chart: [{
    title: 'Availability Information',
    qualifier: 'Chart1',
    chartType: #PIE,
    dimensions:  [ 'OrderStatus' ],
    measures:  [ 'Measure' ]
}]
define view zcustom_order_chart as select from zcustom_order {
    key auftyp as OrderCatagory,
    key case phas0
        when 'X' then 'Open'
        else 'Closed' end as OrderStatus,    
    count(*) as Measure    
} group by phas0, auftyp

Custom Notification CDS View

@AbapCatalog.sqlViewName: 'ZCUSTNOTIF'
@AbapCatalog.compiler.compareFilter: true
@AbapCatalog.preserveKey: true
@OData.publish: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'Custom notification'

@ObjectModel.createEnabled: true
@ObjectModel.deleteEnabled: true
@ObjectModel.updateEnabled: true

define view zcustom_notif
  as select from zcustomnotif
{
@UI : {
    lineItem: [{position: 10 }],
    selectionField: [{position: 10}],
    fieldGroup: [{position: 10,
    qualifier: 'Overview1' },{position: 10, qualifier: 'Header1'}]
}
  key qmnum,
  @UI : {fieldGroup: [{position: 10,
  
    qualifier: 'Overview2' }],
    selectionField: [{position: 20}],
    lineItem: [{position: 20 }]}
  qmtxt,
  @UI : {fieldGroup: [{position: 10,
    qualifier: 'Overview3' }],
    selectionField: [{position: 30}],
    lineItem: [{position: 30 }]}
  qmdat,
  @UI : {fieldGroup: [{position: 10,
    qualifier: 'Overview4' }],
    selectionField: [{position: 40}],
    lineItem: [{position: 40 }]}
  aufnr,
  @UI : {fieldGroup: [{position: 20,
    qualifier: 'Overview1' }],
    selectionField: [{position: 50}],
    lineItem: [{position: 50 }]}
  qmart

}

Manifest –

{
	"_version": "1.8.0",
	"sap.app": {
		"id": "zcustomorder",
		"type": "application",
		"i18n": "i18n/i18n.properties",
		"applicationVersion": {
			"version": "1.0.0"
		},
		"title": "{{appTitle}}",
		"description": "{{appDescription}}",
		"tags": {
			"keywords": []
		},
		"dataSources": {
			"ZCUSTOMORDER_SRV": {
				"uri": "/sap/opu/odata/sap/ZCUSTOMORDER_SRV/",
				"type": "OData",
				"settings": {
					"localUri": "localService/ZCUSTOMORDER_SRV/metadata.xml",
					"annotations": ["localAnnotations", "ZCUSTOMORDER_ANNO_MDL"]
				}
			},
			"localAnnotations": {
				"uri": "annotations/annotations.xml",
				"type": "ODataAnnotation",
				"settings": {
					"localUri": "annotations/annotations.xml"
				}
			},
			"ZCUSTOMORDER_ANNO_MDL": {
				"uri": "/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Annotations(TechnicalName='ZCUSTOMORDER_ANNO_MDL',Version='0001')/$value/",
				"type": "ODataAnnotation",
				"settings": {
					"localUri": ""
				}
			}
		},
		"offline": false,
		"sourceTemplate": {
			"id": "servicecatalog.connectivityComponentForManifest",
			"version": "0.0.0"
		},
		"crossNavigation": {
			"inbounds": {
				"intent1": {
					"signature": {
						"parameters": {},
						"additionalParameters": "allowed"
					},
					"semanticObject": "zcustord",
					"action": "manage"
				}
			},
			"outbounds": {
				"Notification": {
					"semanticObject": "zcustnot",
					"action": "manage"
				}
			}
		}
	},
	"sap.ui": {
		"technology": "UI5",
		"icons": {
			"icon": "",
			"favIcon": "",
			"phone": "",
			"phone@2": "",
			"tablet": "",
			"tablet@2": ""
		},
		"deviceTypes": {
			"desktop": true,
			"tablet": true,
			"phone": true
		},
		"supportedThemes": ["sap_hcb", "sap_belize"]
	},
	"sap.ui5": {
		"resources": {
			"js": [],
			"css": []
		},
		"dependencies": {
			"minUI5Version": "1.38.34",
			"libs": {},
			"components": {}
		},
		"models": {
			"i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"uri": "i18n/i18n.properties"
			},
			"@i18n": {
				"type": "sap.ui.model.resource.ResourceModel",
				"uri": "i18n/i18n.properties"
			},
			"i18n|sap.suite.ui.generic.template.ListReport|zcustom_order": {
				"type": "sap.ui.model.resource.ResourceModel",
				"uri": "i18n/ListReport/zcustom_order/i18n.properties"
			},
			"i18n|sap.suite.ui.generic.template.ObjectPage|zcustom_order": {
				"type": "sap.ui.model.resource.ResourceModel",
				"uri": "i18n/ObjectPage/zcustom_order/i18n.properties"
			},
			"": {
				"type": "sap.ui.model.odata.v2.ODataModel",
				"settings": {
					"defaultOperationMode": "Server",
					"defaultBindingMode": "OneWay",
					"defaultCountMode": "Request"
				},
				"dataSource": "ZCUSTOMORDER_SRV",
				"preload": true
			}
		},
		"extends": {
			"extensions": {
				"sap.ui.controllerExtensions": {
					"sap.suite.ui.generic.template.ObjectPage.view.Details": {
						"controllerName": "zcustomorder.ext.controller.ObjectPageExt",
						"sap.ui.generic.app": {
							"zcustom_order": {
								"EntitySet": "zcustom_order",
								"Header": {
									"Actions": {
										"Notification": {
											"id": "Notification",
											"text": "{@i18n>CREATE}",
											"press": "onCreateNotification"
										}
									}
								}
							}
						}
					},
					"sap.suite.ui.generic.template.ListReport.view.ListReport": {
						"controllerName": "zcustomorder.ext.controller.ListReportExt",
						"sap.ui.generic.app": {
							"zcustom_order": {
								"EntitySet": "zcustom_order",
								"Actions": {}
							}
						}
					}
				}
			}
		},
		"contentDensities": {
			"compact": true,
			"cozy": false
		}
	},
	"sap.ui.generic.app": {
		"_version": "1.3.0",
		"settings": {
			"forceGlobalRefresh": false
		},
		"pages": {
			"ListReport|zcustom_order": {
				"entitySet": "zcustom_order",
				"component": {
					"name": "sap.suite.ui.generic.template.ListReport",
					"list": true,
					"settings": {
						"smartVariantManagement": true,
						"quickVariantSelectionX": {
							"showCounts": false,
							"enableAutoBinding": false,
							"variants": {
								"0": {
									"key": "t0",
									"entitySet": "zcustom_order",
									"annotationPath": "com.sap.vocabularies.UI.v1.SelectionVariant#All"
								},
								"1": {
									"key": "t1",
									"entitySet": "zcustom_order",
									"annotationPath": "com.sap.vocabularies.UI.v1.SelectionVariant#Open"
								},
								"2": {
									"key": "t2",
									"entitySet": "zcustom_order_chart",
									"annotationPath": "com.sap.vocabularies.UI.v1.PresentationVariant#Chart"
								}
							}
						}
					}
				},
				"pages": {
					"ObjectPage|zcustom_order": {
						"entitySet": "zcustom_order",
						"component": {
							"name": "sap.suite.ui.generic.template.ObjectPage"
						}
					}
				}
			}
		}
	},
	"sap.platform.hcp": {
		"uri": ""
	}
}

Local Annotation File –

<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx xmlns:edmx="http://docs.oasis-open.org/odata/ns/edmx" Version="4.0">
	<edmx:Reference Uri="/sap/bc/ui5_ui5/ui2/ushell/resources/sap/ushell/components/factsheet/vocabularies/UI.xml">
		<edmx:Include Alias="UI" Namespace="com.sap.vocabularies.UI.v1"/>
	</edmx:Reference>
	<edmx:Reference Uri="/sap/opu/odata/sap/ZCUSTOM_ORDER_CDS/$metadata">
		<edmx:Include Alias="ZCUSTOM_ORDER_CDS" Namespace="ZCUSTOM_ORDER_CDS"/>
	</edmx:Reference>
	<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Aggregation.V1.xml">
		<edmx:Include Alias="Aggregation" Namespace="Org.OData.Aggregation.V1"/>
	</edmx:Reference>
	<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Authorization.V1.xml">
		<edmx:Include Alias="Auth" Namespace="Org.OData.Authorization.V1"/>
	</edmx:Reference>
	<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Capabilities.V1.xml">
		<edmx:Include Alias="Capabilities" Namespace="Org.OData.Capabilities.V1"/>
	</edmx:Reference>
	<edmx:Reference Uri="https://wiki.scn.sap.com/wiki/download/attachments/448470974/Common.xml?api=v2">
		<edmx:Include Alias="Common" Namespace="com.sap.vocabularies.Common.v1"/>
	</edmx:Reference>
	<edmx:Reference Uri="https://wiki.scn.sap.com/wiki/download/attachments/448470971/Communication.xml?api=v2">
		<edmx:Include Alias="Communication" Namespace="com.sap.vocabularies.Communication.v1"/>
	</edmx:Reference>
	<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Core.V1.xml">
		<edmx:Include Alias="Core" Namespace="Org.OData.Core.V1"/>
	</edmx:Reference>
	<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Measures.V1.xml">
		<edmx:Include Alias="Measures" Namespace="Org.OData.Measures.V1"/>
	</edmx:Reference>
	<edmx:Reference Uri="https://oasis-tcs.github.io/odata-vocabularies/vocabularies/Org.OData.Validation.V1.xml">
		<edmx:Include Alias="Validation" Namespace="Org.OData.Validation.V1"/>
	</edmx:Reference>
	<edmx:DataServices>
		<Schema xmlns="http://docs.oasis-open.org/odata/ns/edm" Namespace="zcustomorder.ZCUSTOMORDER_SRV">
			<!--==========================================================
                Entity Type from chosen collection 
                ==========================================================-->
			<Annotations Target="ZCUSTOMORDER_SRV.zcustom_orderType">
				<Annotation Term="UI.SelectionVariant" Qualifier="Open">
					<Record Type="UI.SelectionVariantType">
						<PropertyValue Property="ID" String="SEL02"/>
						<PropertyValue Property="Text" String="{@i18n>OPEN}"/>
						<PropertyValue Property="SelectOptions">
							<Collection>
								<Record Type="UI.SelectOptionType">
									<PropertyValue Property="PropertyName" PropertyPath="phas0"/>
									<PropertyValue Property="Ranges">
										<Collection>
											<Record Type="UI.SelectionRangeType">
												<PropertyValue Property="Sign" EnumMember="UI.SelectionRangeSignType/I"/>
												<PropertyValue Property="Option" EnumMember="UI.SelectionRangeOptionType/EQ"/>
												<PropertyValue Property="Low" Bool="true"/>
											</Record>
										</Collection>
									</PropertyValue>
								</Record>
							</Collection>
						</PropertyValue>
					</Record>
				</Annotation>
				<Annotation Term="UI.SelectionVariant" Qualifier="All">
					<Record Type="UI.SelectionVariantType">
						<PropertyValue Property="ID" String="SEL01"/>
						<PropertyValue Property="Text" String="{@i18n>ALL}"/>
					</Record>
				</Annotation>
				<Annotation Term="UI.HeaderFacets">
					<Collection>
						<Record Type="UI.ReferenceFacet">
							<PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#Header1"/>
						</Record>
					</Collection>
				</Annotation>
				<Annotation Term="UI.Facets">
					<Collection>
						<Record Type="UI.CollectionFacet">
							<PropertyValue Property="ID" String="GeneralInformation"/>
							<PropertyValue Property="Label" String="{@i18n>OVERVIEW}"/>
							<PropertyValue Property="Facets">
								<Collection>
									<Record Type="UI.ReferenceFacet">
										<PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#Overview1"/>
									</Record>
									<Record Type="UI.ReferenceFacet">
										<PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#Overview2"/>
									</Record>
									<Record Type="UI.ReferenceFacet">
										<PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#Overview3"/>
									</Record>
									<Record Type="UI.ReferenceFacet">
										<PropertyValue Property="Target" AnnotationPath="@UI.FieldGroup#Overview4"/>
										<PropertyValue Property="ID" String="RF1"/>
									</Record>
								</Collection>
							</PropertyValue>
						</Record>
					</Collection>
				</Annotation>
			</Annotations>
			<Annotations Target="ZCUSTOMORDER_SRV.ZCUSTOMORDER_SRV_Entities/zcustom_order">
				<Annotation Term="Capabilities.UpdateRestrictions">
					<Record Type="Capabilities.UpdateRestrictionsType">
						<PropertyValue Property="Updatable" Path="phas0"/>
					</Record>
				</Annotation>
				<Annotation Term="Capabilities.DeleteRestrictions">
					<Record Type="Capabilities.DeleteRestrictionsType">
						<PropertyValue Property="Deletable" Path="phas0"/>
					</Record>
				</Annotation>
			</Annotations>
			<Annotations Target="ZCUSTOMORDER_SRV.zcustom_order_chartType">
				<Annotation Term="UI.PresentationVariant" Qualifier="Chart">
					<Record Type="UI.PresentationVariantType">
						<PropertyValue Property="Visualizations">
							<Collection>
								<AnnotationPath>@UI.Chart#Chart1</AnnotationPath>
							</Collection>
						</PropertyValue>
						<PropertyValue Property="ID" String="CH1"/>
						<PropertyValue Property="Text" String="{@i18n>CHART}"/>
					</Record>
				</Annotation>
			</Annotations>
			<Annotations Target="ZCUSTOMORDER_SRV.zcustom_notifType">
				<Annotation Term="UI.FilterFacets">
					<Collection/>
				</Annotation>
			</Annotations>
		</Schema>
	</edmx:DataServices>
</edmx:Edmx>

List Report Extension –

sap.ui.controller("zcustomorder.ext.controller.ListReportExt", {
	onInit: function(){
		//Somehow the chart entity is not called automatically so we need to call it explicitly to load
		this._loadChart();
		//Auto value help logic for Smart Filter 
		var smFilt = this.getView().byId(
			"zcustomorder::sap.suite.ui.generic.template.ListReport.view.ListReport::zcustom_order--listReportFilter"
		);
		var conConfig = smFilt.getControlConfiguration();
		conConfig.forEach(function(item, idx, arr){
			smFilt.removeControlConfiguration(item);
			item.setPreventInitialDataFetchInValueHelpDialog(false);
			smFilt.addControlConfiguration(item);
		}, this);
	},
	
	onAfterRendering: function () {
		// Current timestamp set as default filter for order start but this way we can set any field dynamically
		var smFilt = this.getView().byId(
			"zcustomorder::sap.suite.ui.generic.template.ListReport.view.ListReport::zcustom_order--listReportFilter"
		);
		var dat = new Date();//Java script date object
		var datStr = dat.toISOString(); // Convert it to format that SAP understands
		var jsonString =
			'{"SelectionVariantID":"","Parameters":[{"PropertyName":"orderstart","PropertyValue":"' + datStr +'"}]}';
		smFilt.setDataSuiteFormat(jsonString);
	},
	
	_loadChart: function(){
		var url = "/zcustom_order_chart";
		var oModel = this.getOwnerComponent().getModel();
		var params = {
			async: false,
			success: function (oData, controller) {
				//Do nothing. The Smart chart will automatically read it. 
				sap.ui.core.BusyIndicator.hide();
			},
			error: function (oError) {
				sap.ui.core.BusyIndicator.hide();
			}
		};
		oModel.read(url, params);
	}
});

Object Page Extension –

sap.ui.controller("zcustomorder.ext.controller.ObjectPageExt", {
	onInit: function () {
		that = this;
		
		//Automatic value help for Object Page smart field
		var fld = this.oView.byId("zcustomorder::sap.suite.ui.generic.template.ObjectPage.view.Details::zcustom_order--RF1::qmnum::Field");
		if (fld) {
			var oConfig = fld.getConfiguration();
			if (!oConfig) {
				oConfig = new sap.ui.comp.smartfield.Configuration();
			}
			oConfig.setPreventInitialDataFetchInValueHelpDialog(false);
			oConfig.setDisplayBehaviour(sap.ui.comp.smartfield.DisplayBehaviour.descriptionAndId);
			fld.setConfiguration(oConfig);
		}
		
		//Convert Smart field into URL
		var notifFld = this.getView().byId(
			"zcustomorder::sap.suite.ui.generic.template.ObjectPage.view.Details::zcustom_order--RF1::qmnum::Field"
		);
		if (notifFld) {
			notifFld.attachPress(this.onNotifPress);
		}
	},
	
	onNotifPress : function(){
		var sPath = that.getView().getBindingContext().getPath();
		var notifNo = that.getView().getModel().getProperty(sPath + "/qmnum");
		var oNavControl = that.extensionAPI.getNavigationController();
		oNavControl.navigateExternal("Notification", {
			qmnum: notifNo
		});
	},
	
	onAfterRendering: function () {
		this._oEditButton = this.getView().byId(
			"zcustomorder::sap.suite.ui.generic.template.ObjectPage.view.Details::zcustom_order--edit");
		this._oEditButton.attachPress(this.onEditPress);
	},
	
	onEditPress : function(){
		sap.m.MessageToast.show("Edit button pressed");
	},

	onCreateNotification: function (oEvent) {
		var oNavControl = this.extensionAPI.getNavigationController();
		var oModel = this.getOwnerComponent().getModel();
		var sPath = oEvent.getSource().getBindingContext().getPath();
		var notNo = oModel.getProperty(sPath + "/qmnum");
		var ordNo = oModel.getProperty(sPath + "/aufnr");
		var ordStart = oModel.getProperty(sPath + "/orderstart");
		oNavControl.navigateExternal("Notification", {
			qmnum: notNo,
			aufnr: ordNo,
			qmdat: ordStart,
			preferredMode: "create"
		});

	}
});

Leave a Reply

Your email address will not be published. Required fields are marked *