Extend SAP Fiori Demo Cloud Application
Introduction :
SAP Fiori Cloud Demo is a useful Cloud application, it offers a list of SAP Standard apps. We can try/extend those apps easily. Before this i remember the first time when i spent hours to patch my on-premise system with correct Add-on’s, activation Odata services and managing roles for user to start working with Fiori LaunchPad it was a real headache.
With SAP Fiori Demo all the installation/Configuration stuff is already done and we can directly choose our Fiori app to adapt it to our business scenario
Go to https://www.sapfioritrial.com/. You will need an SCN account to use customize apps here.
Click the Customize & Extend icon from the upper bar
Click Get Started Button
Use your SAP SCN ID if you have it otherwise you need to create a new one
Extension project, step-by-step :
For this exercise i will choose “My Leave Request”. The app is available here
https://www.sapfioritrial.com/sites?helpset=trial&sap-client=001#LeaveRequest-manage
My new extension will change two things :
- Add a Background color for quota fields.
- Activate The Approver text-field and use a value Help instead.
Change the Layout to switch to Dev mode
Create your extension project
The Workspace should look like
Use the Extensibility tool
Switch to Extensibility mode
Find the position of elements i want to extend, the both controls are available in S1 View
Change the CSS for BOOKEDDAYS and REMAININGDAY Content
Back to my extension project in the WEB IDE. Right-Click on webapp folder -> New -> Folder
Choose a name for this folder ( css ) and click ok
Right-Click on css folder -> New -> File. Choose a name ( myStyleSheet.css ) and click ok
myStyleSheet.css content :
.myLRColor .myCustomBGtRed
{
font-weight: bold;
font-size: x-large;
background:red
}
.myLRColor .myCustomBGtGreen
{
font-weight: bold;
font-size: x-large;
background:green
}
Reference the css file in component.js script
jQuery.sap.declare("hcm.myleaverequest.hcmmyleaverequestExtension.Component");
// use the load function for getting the optimized preload file if present
sap.ui.component.load({
name: "hcm.myleaverequest",
// Use the below URL to run the extended application when SAP-delivered application is deployed on cloud
url: jQuery.sap.getModulePath("hcm.myleaverequest.hcmmyleaverequestExtension") + "/parent" // we use a URL relative to our own component
// extension application is deployed with customer namespace
});
this.hcm.myleaverequest.Component.extend("hcm.myleaverequest.hcmmyleaverequestExtension.Component", {
metadata: {
version: "1.0",
// ONGABI Extension DEL CONTENT - BEGIN //
includes: ["css/myStyleSheet.css"],
// ONGABI Extension DEL CONTENT - END //
config: {},
customizing: {
"sap.ui.viewReplacements": {
"hcm.myleaverequest.view.S1": {
"viewName": "hcm.myleaverequest.hcmmyleaverequestExtension.view.S1Custom",
"type": "XML"
}
}
}
}
});
S1Custom.view.xml content :
I replaced the Class used before by the new style
<!--
Copyright (C) 2009-2014 SAP SE or an SAP affiliate company. All rights reserved
-->
<!--Copyright (C) 2009-2013 SAP AG or an SAP affiliate company. All rights reserved-->
<sap.ui.core:View id="S1" xmlns="sap.m" xmlns:sap.ui.layout.form="sap.ui.layout.form" xmlns:sap.ui.layout="sap.ui.layout"
xmlns:sap.me="sap.me" xmlns:sap.ui.core="sap.ui.core" xmlns:ui="sap.ca.ui" xmlns:sap.ui.unified="sap.ui.unified"
controllerName="hcm.myleaverequest.view.S1">
<!-- ONGABI Extension DEL CONTENT - BEGIN -->
<!--<Page id="S1_page" title="{i18n>LR_TITLE_HOME_VIEW}">-->
<!-- ONGABI Extension DEL CONTENT - DEL -->
<!-- ONGABI Extension INS CONTENT - BEGIN -->
<Page id="S1_page" title="{i18n>LR_TITLE_HOME_VIEW}" class="myLRColor">
<!-- ONGABI Extension INS CONTENT - DEL -->
<content>
<sap.ui.layout:Grid id="LRS4_FLX_TOP" width="auto" defaultIndent="L4 M3" defaultSpan="L4 M6 S12" class="s4leaveTypeSelectorFlx">
<sap.ui.layout:content>
<Select id="SLCT_LEAVETYPE" change="onSelectionChange" width="100%"></Select>
</sap.ui.layout:content>
</sap.ui.layout:Grid>
<sap.ui.layout:Grid defaultSpan="L12 M12 S12" width="auto">
<sap.ui.layout:content>
<sap.ui.layout.form:Form id="LRS4_FRM_MAIN" minWidth="1024" maxContainerCols="2">
<sap.ui.layout.form:layout>
<sap.ui.layout.form:ResponsiveGridLayout labelSpanL="3" labelSpanM="3" emptySpanL="4" emptySpanM="4" columnsL="1" columnsM="1"/>
</sap.ui.layout.form:layout>
<sap.ui.layout.form:formContainers>
<sap.ui.layout.form:FormContainer id="LRS4_FRM_CNT_CALENDAR">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData weight="6" linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:formElements>
<sap.ui.layout.form:FormElement id="LRS4_FELEM_CALENDAR">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:fields>
<sap.me:Calendar id="LRS4_DAT_CALENDAR" class="s4Calendar"></sap.me:Calendar>
<sap.me:CalendarLegend id="LRS4_LEGEND" class="s4LEGEND" legendWidth="18em">
<sap.me:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData id="LRS4_LYO_LEGEND" minWidth="30" weight="15"></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.me:layoutData>
</sap.me:CalendarLegend>
</sap.ui.layout.form:fields>
</sap.ui.layout.form:FormElement>
</sap.ui.layout.form:formElements>
</sap.ui.layout.form:FormContainer>
<sap.ui.layout.form:FormContainer id="LRS4_FRM_CNT_BALANCES">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData weight="3"></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:formElements>
<sap.ui.layout.form:FormElement id="LRS4_FELEM_BALANCES">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:fields>
<sap.ui.layout:Grid width="100%" defaultSpan="L6 M6 S6">
<sap.ui.layout:content>
<!-- ONGABI Extension DEL CONTENT - BEGIN -->
<!--<sap.ui.layout:VerticalLayout id="LRS4_TXT_BOOKEDDAYS" class="s4BalancesFlxLeft" width="100%">-->
<!-- ONGABI Extension DEL CONTENT - END -->
<!-- ONGABI Extension INS CONTENT - BEGIN -->
<sap.ui.layout:VerticalLayout id="LRS4_TXT_BOOKEDDAYS" width="100%" class="myCustomBGtRed">
<!-- ONGABI Extension INS CONTENT - END -->
<BusyIndicator id="LRS1_BUSY_BOOKEDDAYS" size="1em" visible="true"></BusyIndicator>
<ObjectNumber id="LRS4_TXT_BOOKED_DAYS" class="s4BALANCEOBJECT" number="{TimeAccount>BalanceTotalUsedQuantity}"
unit="{TimeAccount>TimeUnitName}" visible="false">
<layoutData>
<FlexItemData growFactor="1"></FlexItemData>
</layoutData>
</ObjectNumber>
<ObjectStatus id="LRS4_TXT_BOOKED" text="{i18n>LR_BALANCE_USED}">
<layoutData>
<FlexItemData growFactor="1"></FlexItemData>
</layoutData>
</ObjectStatus>
</sap.ui.layout:VerticalLayout>
<!-- ONGABI Extension DEL CONTENT - BEGIN -->
<!--<sap.ui.layout:VerticalLayout id="LRS4_TXT_REMAININGDAY" class="s4BalancesFlxRight" width="100%">-->
<!-- ONGABI Extension DEL CONTENT - END -->
<!-- ONGABI Extension INS CONTENT - BEGIN -->
<sap.ui.layout:VerticalLayout id="LRS4_TXT_REMAININGDAY" width="100%" class="myCustomBGtGreen">
<!-- ONGABI Extension INS CONTENT - END -->
<BusyIndicator id="LRS1_BUSY_REMAININGDAYS" size="1em" visible="true"></BusyIndicator>
<ObjectNumber id="LRS4_TXT_REMAINING_DAYS" class="s4BALANCEOBJECT" number="{TimeAccount>BalanceAvailableQuantity}"
unit="{TimeAccount>TimeUnitName}" visible="false">
<layoutData>
<FlexItemData growFactor="1"></FlexItemData>
</layoutData>
</ObjectNumber>
<ObjectStatus id="LRS4_TXT_REMAINING" text="{i18n>LR_BALANCE_BALANCE}">
<layoutData>
<FlexItemData growFactor="1"></FlexItemData>
</layoutData>
</ObjectStatus>
</sap.ui.layout:VerticalLayout>
</sap.ui.layout:content>
</sap.ui.layout:Grid>
</sap.ui.layout.form:fields>
</sap.ui.layout.form:FormElement>
<sap.ui.layout.form:FormElement id="LRS4_FELEM_TIMEINPUT" visible="false">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:fields>
<sap.ui.layout:Grid width="100%" defaultSpan="L6 M6 S6">
<sap.ui.layout:content>
<sap.ui.layout:VerticalLayout width="100%">
<Label id="LRS4_LBL_STARTTIME" text="{i18n>LR_START_TIME}"></Label>
<DateTimeInput id="LRS4_DAT_STARTTIME" change="onTimeChange" type="Time" valueFormat="HH:mm"></DateTimeInput>
</sap.ui.layout:VerticalLayout>
<sap.ui.layout:VerticalLayout width="100%">
<Label id="LRS4_LBL_ENDTIME" text="{i18n>LR_END_TIME}"></Label>
<DateTimeInput id="LRS4_DAT_ENDTIME" change="onTimeChange" type="Time" valueFormat="HH:mm"></DateTimeInput>
</sap.ui.layout:VerticalLayout>
</sap.ui.layout:content>
</sap.ui.layout:Grid>
</sap.ui.layout.form:fields>
</sap.ui.layout.form:FormElement>
<sap.ui.layout.form:FormElement id="LRS4_FELEM_ABSENCE" visible="false">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:fields>
<sap.ui.layout:Grid width="100%" defaultSpan="L12 M12 S12">
<sap.ui.layout:content>
<sap.ui.layout:VerticalLayout width="100%">
<Label id="LRS4_LBL_ABS_HOURS" text="{i18n>LR_ABS_HOURS}"></Label>
<Input id="LRS4_ABS_HOURS" change="onAbsenceHoursChange" maxLength="10"></Input>
</sap.ui.layout:VerticalLayout>
</sap.ui.layout:content>
</sap.ui.layout:Grid>
</sap.ui.layout.form:fields>
</sap.ui.layout.form:FormElement>
<sap.ui.layout.form:FormElement id="LR_FELEM_APPROVER">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:fields>
<sap.ui.layout:Grid id="LR_APPROVER" width="100%" defaultSpan="L12 M12 S12">
<sap.ui.layout:content>
<Label id="LRS4_LBL_APPROVER" text="{i18n>LR_APPROVER}">
<layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</layoutData>
</Label>
<Input id="LRS4_APPROVER_NAME" type="Text" showSuggestion="true" valueHelpOnly="true" showValueHelp="true"
valueHelpRequest="handleValueHelp"></Input>
</sap.ui.layout:content>
</sap.ui.layout:Grid>
</sap.ui.layout.form:fields>
</sap.ui.layout.form:FormElement>
<sap.ui.layout.form:FormElement id="LRS4_FELEM_NOTE">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:fields>
<sap.ui.layout:Grid id="LRS4_NOTE" width="100%" defaultSpan="L12 M12 S12">
<sap.ui.layout:content>
<Label id="LRS4_LBL_NOTE" text="{i18n>LR_NOTE}">
<layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</layoutData>
</Label>
<TextArea id="LRS4_TXA_NOTE" class="s4Notes " width="100%" height="6rem" wrapping="None" maxLength="255">
<layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData weight="8" linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</layoutData>
</TextArea>
</sap.ui.layout:content>
</sap.ui.layout:Grid>
</sap.ui.layout.form:fields>
</sap.ui.layout.form:FormElement>
<sap.ui.layout.form:FormElement visible="false" id="LRS4_FELEM_FILEATTACHMENTS">
<sap.ui.layout.form:layoutData>
<sap.ui.layout:ResponsiveFlowLayoutData linebreak="true"></sap.ui.layout:ResponsiveFlowLayoutData>
</sap.ui.layout.form:layoutData>
<sap.ui.layout.form:fields>
<sap.ui.layout:Grid id="LRS4_FILEATTACHMENTS" width="100%" defaultSpan="L12 M12 S12">
<sap.ui.layout:content>
<sap.ui.unified:FileUploader id="fileUploader" width="100%" uploadUrl="" placeholder="{i18n>LR_ATTACHMENT}" uploadOnChange="false"
uploadComplete="handleUploadComplete" change="handleValueChange" typeMissmatch="handleTypeMissmatch" style="Emphasized" useMultipart="false"></sap.ui.unified:FileUploader>
<UploadCollection id="fileupload" visible="false" uploadEnabled="false" editMode="false" items="{files>/AttachmentsCollection}">
<UploadCollectionItem contributor="{files>Contributor}" documentId="{files>DocumentId}" enableDelete="false" enableEdit="false"
url="{files>FileUrl}" mimeType="{files>MimeType}" fileName="{files>FileName}" fileSize="{files>FileSize}"
uploadedDate="{files>UploadedDate}"></UploadCollectionItem>
</UploadCollection>
</sap.ui.layout:content>
</sap.ui.layout:Grid>
</sap.ui.layout.form:fields>
</sap.ui.layout.form:FormElement>
<!-- extension point for additional fields -->
<sap.ui.core:ExtensionPoint name="extS1Field"></sap.ui.core:ExtensionPoint>
</sap.ui.layout.form:formElements>
</sap.ui.layout.form:FormContainer>
</sap.ui.layout.form:formContainers>
<sap.ui.layout.form:layout>
<sap.ui.layout.form:ResponsiveLayout id="LRS4_FRM_MAIN_LAYOUT"></sap.ui.layout.form:ResponsiveLayout>
</sap.ui.layout.form:layout>
</sap.ui.layout.form:Form>
</sap.ui.layout:content>
</sap.ui.layout:Grid>
</content>
</Page>
</sap.ui.core:View>
Again navigate to Extensibility Panel
In S1.controller.js ( the original controller to My Leave Request ) i found a method _leaveTypeDependantSettings() which is responsible to setting an enabled mode to LRS4_APPROVER_NAME component. Unfortunately this method is not available in standard extensible methods
I will Extend by copy my controller
Select all commented lines and uncomment the content
Comment this line in _leaveTypeDependantSettings() method
Extension Test :
Select index.html in the extension project and click RUN
The result match with my initial need. Great !!!!
Extension Deployment :
The application is now ready, we can deploy it on the Fiori portal
Enjoy.
Great tutorial. Thanks!
Let me ask you a question:
If i have a Fiori app that i need to extend but the object/part is not extensible, what options do i have?
Create a custom copy of the app like a custom abap program?
Best Regards.
Hi,
Thanks for your support.
For your questions i think this post give you a real idea of how to extend Fiori app part without standard extension entry point.
Regards.