End-to-End How-to Guide: Building a SAP UI5 Application on ...
Transcript of End-to-End How-to Guide: Building a SAP UI5 Application on ...
End-to-End How-to Guide: Building a SAP UI5 Application on top of SAP Customer Activity Repository
Content Content .................................................................................................................................................... 1
1 Overview.......................................................................................................................................... 2
2 Prerequisites .................................................................................................................................... 2
2.1 Setup SAP CAR Instance with SAP CAL .................................................................................... 2
2.1.1 Start and Connect to SAP CAR ......................................................................................... 4
3 SAP HANA Studio ............................................................................................................................. 6
4 Content Package and XS Project ..................................................................................................... 8
4.1 Create a new Package ............................................................................................................. 8
4.2 Create a new SAP XS Project ................................................................................................... 8
4.3 Modify the .xsaccess file ........................................................................................................ 12
5 Application for Order Channel Analysis ........................................................................................ 13
5.1 Virtual Data Model ................................................................................................................ 13
5.2 Server Side development ...................................................................................................... 14
5.2.1 Copy MultiChannelSales calculation view ..................................................................... 15
5.2.2 Adjusting MULTICHANNELSALES calculation view ........................................................ 17
5.2.3 XS OData services .......................................................................................................... 19
5.3 Web Content development ................................................................................................... 23
5.3.1 Folder Structure ............................................................................................................. 23
5.3.2 Index File ....................................................................................................................... 23
5.3.3 Model View Controller .................................................................................................. 25
5.3.4 Home, Master and Detail .............................................................................................. 32
6 Appendix ........................................................................................................................................ 39
6.1 Home view ............................................................................................................................. 39
6.2 Home controller .................................................................................................................... 39
6.3 Master controller................................................................................................................... 40
6.4 Detail view ............................................................................................................................. 42
6.5 Detail controller ..................................................................................................................... 42
1 Overview
This document describes the end-to-end process, required to develop an SAPUI5 application for
consuming data from the SAP Customer Activity Repository content, specifically the underlying SAP
HANA database. The application runs on an SAP CAR instance (SAP Customer Activity Repository 1.0
SP01 - Developer Edition for Partners), created from the SAP Cloud Appliance Library (SAP CAL).
The SAP CAR instance runs on an SAP NetWeaver 7.40 SP5 Application Server ABAP on SAP HANA.
The SAP HANA version is 1.00.74 on the used instance. This document starts with the complete setup
process of an SAP CAR instance from SAP CAL. Afterwards the modification and consumption of the
Virtual Data Models1 as the data foundation will be explained. Finally the building of the SAPUI5
application will be described in detail. The scenario of return amount analysis by order channels and
articles is used for a mobile SAPUI5 sample application, to show the readiness and high abstraction
level for analytical data consumption.
2 Prerequisites
The reader should have an SAP S-User and a purchased license for “SAP Cloud Appliance
Library for Partners“ from the SAP Store2 or an appropriate on premise SAP CAR
development system with at least the revision level, listed above
For hosting the SAP CAR instance an Amazon Web Services (AWS) account is needed
This AWS account has to be associated with the SAP Cloud Appliance library (see tab
“Accounts”)
The user should have basic understanding in SAPUI5 programming (e. g. JavaScript and Web
Technologies, such as ODATA an HTML5)
2.1 Setup SAP CAR Instance with SAP CAL
For this how-to guide we need a running SAP Customer Activity Repository (CAR) instance. This
instance can be easily created on SAP Cloud Appliance Library (CAL).
1. Go to the SAP CAL (https://cal.sap.com/ ) and login. You can find the login button in the right
upper corner
2. Select the tab Solutions and activate “SAP Customer Activity Repository 1.0 SP01 - Developer
Edition for Partners”. It is a prerequisite that you have unlocked the access by purchasing the
license as described in the prerequisite chapter
1http://help.sap.com/saphelp_car100/helpdata/en/1c/cc13c724e94a5c995020d92a691490/content.
htm?frameset=/en/be/ddba516d9ef93ae10000000a44176d/frameset.htm¤t_toc=/en/66/364
77202734290bbb74c08d9929d7d/plain.htm&node_id=229&show_children=true#jump229
2 https://store.sap.com/sap/cp/ui/resources/store/html/SolutionDetails.html?pid=0000013279
3. Now you have to create an SAP CAR instance in the Solutions tab, select “Create Instance”
a. Enter the general properties:
b. Configure the virtual machine:
The SAP CAR instance includes two virtual machines – one for the backend and one
the frontend system. For the Backend system you need an r3.2xlarge AWS instance,
for the frontend an m3.medium AWS instance as recommended by SAP:
c. Choose an Administrator password. You will need this password for several different
issues, therefore please note down this password
d. Finally, you can define the schedule of the instance, as you prefer:
e. Click on “Finish” to end the instance creation process
2.1.1 Start and Connect to SAP CAR
1. Now you can find the SAP CAR instances in the tab “Instances” in SAP CAL
2. Click on “Activate” to start the instance. This can take up to 10 minutes
3. When the System is running you see a green sign
4. Now you can click now on “Connect” and select “Remote
Desktop (SAP Frontend)” to access the frontend system. On this system you can find a SAP
GUI and a preconfigured SAP HANA Studio
5. To connect with Remote Desktop you have to use the user “Administrator” and your master
password, which you defined during the setup of the instance
6. Now you can start the SAP HANA Studio on the desktop of the frontend system
7. If you want to shut down the SAP CAR instance go to SAP CAL (https://cal.sap.com) and
select the tab instances. Click on “Suspend” to shut down the
instance. This will not terminate the instance
8. For further options like rebooting, terminating instance etc. please refer to the
3 SAP HANA Studio This chapter will briefly describe, how to connect the SAP HANA Studio to the previously described
SAP CAR instance in the SAP CAL environment, from your local machine.
1. Skip this step if your instances is already running. To start your SAP CAR server from
https://cal.sap.com
a. Log into Cloud Appliance Library (CAL)
b. Go to the tab “Instances” and click “Activate” , which usually takes about
10 minutes
2. Download and Install the SAP HANA Studio as described here
https://tools.hana.ondemand.com/#hanatools
3. In the SAP HANA Modeler perspective , right click into the free space
below the left hand side Systems view and click “Add System”
4. Note the IP address of your HANA instance by clicking the CAL instance at
https://cal.sap.com
5. Add the for the Host Name the IP address and 02 for Instance Number, choose your
description and click “Next”
6. Add SYSTEM user with the same password, which you have chosen during your CAL instance
creation (see above), click “Finish”
The System will appear in your Systems View as follows:
4 Content Package and XS Project Since we would like to demonstrate the possibilities of using SAP CAR content by partners, we use
the so called SAP Extended Application Services3 (refer to XS) for application development.
For the development of the SAPUI5 sample application, we need a repository package in the SAP
HANA Content folder and the appropriate SAP XS project. Further, we will reuse the SAP CAR
standard content, such as Virtual Data Models4. We can modify this content, by copying the original
object into our package with the custom namespace. Further, this package will contain all
development artifacts that can be easily encapsulated by a Delivery Unit and transported to other
SAP CAR systems by the SAP partner.
4.1 Create a new Package 1. Logon to the HANA database (RTP) with user SYSTEM (SAP HANA Studio on your local
machine, or Remote Desktop of your CAL instance, see above)
2. Create a new Package by right-clicking on “Content”, select “New”, select “Package”
a. Enter Name: “PartnerApplications”, your description and “OK”.
4.2 Create a new SAP XS Project This chapter contains the prerequisites for native SAP HANA development. Therefore, we create a
new XS project which is the foundation for the further described application development.
3 http://help.sap.com/hana/SAP_HANA_Developer_Guide_for_SAP_HANA_Studio_en.pdf p.15 4 http://help.sap.com/saphelp_car100/helpdata/de/11/ddba516d9ef93ae10000000a44176d/content.htm
1. Choose the SAP HANA Development perspective in the SAP
HANA Studio, please go to the Project Explorer view and right-click in
the free area below, select “New” and then “Other”
2. Type “xs” in the Filter section and chose “XS Project” and click “Next”
3. Add Project Name: “OrderChannelAnalysis”, leave all check boxes as the picture shows, we
need to share the project in the repository as suggested, press “Next”
4. Mark your active repository and leave check box “Add Project Folder as Subpackage”
selected, click on “Browse” to associate with our development package
5. Choose “PartnerApplications” and click “OK”
6. Click “Next”, you will see following window, create both access objects and leave common
objects blanc, click “Finish” to and this step
Each application that you want to develop and deploy on SAP HANA Extended Application Services
(SAP HANA XS) must have an application-descriptor file (.xsapp file). The application descriptor is the
core file that you use to describe an application's framework within SAP HANA XS (for more
information see here5). SAP HANA XS enables you to define access to each individual application
package that you want to develop and deploy, therefore an .xsaccess file will generated as well.
5http://help.sap.com/saphelp_hanaplatform/helpdata/en/05/49991ea9984835b8c06c12123b7fe2/content.htm?frameset=/en/05/49991ea9984835b8c06c12123b7fe2/frameset.htm¤t_toc=/en/34/29fc63a1de4cd6876ea211dc86ee54/plain.htm&node_id=66&show_children=false
7. The following will appear in your Project Explorer
4.3 Modify the .xsaccess file The application access file enables you to specify who or what is authorized to access the content
exposed by a SAP HANA XS application package and which content they are allowed to see. Here we
use a form based authentication with the appropriate database user, for more information please
refer to6.
1. Copy the following code into the .xsaccess file:
{
"exposed" : true,
"authentication" :
{
"method": "Form"
}
}
1. Save and activate the file .
6http://help.sap.com/saphelp_hanaplatform/helpdata/en/5f/e3b123826d4503aa66eb955a002821/content.htm
5 Application for Order Channel Analysis
After all preparations have been fulfilled, we are ready to implement the SAPUI5 sample application,
which will consume SAP CAR content, specifically the Multichannel view from the appropriate VDM.
After a short description of the Multichannel Sales context, we will copy the content for a slight
modification, showing the approach of reusing SAP CAR content in a partner development context.
This chapter contains the description of the implementation of a simple mobile app in a fiori style
split app, for Order Channel Analysis. Therefore, we first describe server side development artifacts,
such as the copied and modified calculation view as data model and the OData services. In the next
step we will describe the implementation of a SAPUI5 web application. The user can visualize the
amount of returns by order channels in a pie chart and drill down into a specific order channel, to
analyze returns by the appropriate articles with the presented app.
With this step-by-step guide one can implement the example application.
5.1 Virtual Data Model
The basis of this document is to show, how SAP partners can reuse SAP HANA Content for SAP
Customer Activity Repository in their partner application development.
The SAP HANA Content for SAP Customer Activity Repository is a collection of views on the data
stored in your SAP HANA database, the so called virtual data model (VDM). Some of this data, for
example sales documents, is accessed by SAP Customer Activity Repository from other source
systems. Other data, for example, point-of-sale transactions, is created by the SAP Customer Activity
Repository application7.
The observed VDM provides the prerequisites for analyzing the combined sales and transactional
data across all channels to be used in controlling, marketing, promotion management, and
monitoring retailing processes. This VDM consolidates the information provided by the POS
Transaction Sales Analysis and Sales Analysis Based on Billing Documents VDMs to give you an overall
view of customer’s transactional activities across channels. 8
Specifically, we will show how partner can reuse the MultiChannelSales view as part of the VDM
(please find the overview of the VDM and the used view in this example in the image below).
You can find the appropriate Calculation View in the HANA Studio under Systems -> RTP -> Content ->
sap -> is -> retail -> car -> „MultiChannelSales“.
7 http://help.sap.com/saphelp_car200/helpdata/en/1c/cc13c724e94a5c995020d92a691490/content.htm 8http://help.sap.com/saphelp_car100/helpdata/en/d2/d085d9c89b4660b41a61233dd49eee/content.htm?frameset=/en/1c/cc13c724e94a5c995020d92a691490/frameset.htm¤t_toc=/en/66/36477202734290bbb74c08d9929d7d/plain.htm&node_id=237
5.2 Server Side development
For all server side artifacts, we will create a new package called “Server”. Here we will copy the
MultiSalesChannel calculation view and create OData services, to consume this view in the web
application.
1. Right click on the OrderChannelAnalysis package, choose “New” “Package…”
2. Call the sub package “Server”, choose desciption and click “OK”
3. Add a sub package called “Model” accordingly beneath “Server”. This Folder will be used for
our data model e. g. the copy of the MultiSalesChannel calculation view
5.2.1 Copy MultiChannelSales calculation view
The original SAP CAR object can be found SAP HANA Development perspective in the Systems view
under Content->sap->is->retail->car->”Calculation Views”
1. Simply right click on the MultiChannelSales view and click “Copy”
2. Paste the previously copied MultiChannelSales calculation view into the Model package (see
step 1.), by right clicking
3. You can keep the name “MULTICHANNELSALES” as suggested in capital letters, since we will
reuse it in our own namespace, click “ OK”
4. In the final step, we will activate the copied calculation view, by right clicking and “Activate”
5.2.2 Adjusting MULTICHANNELSALES calculation view
In order to be able to select specific order channels in the application, we need to modify the
calculation view. Therefore, we need to define an input parameter for our Multichannel analysis.
1. Change to Project Explorer view, to see the recent changes, right click on Server->Model and
click on Team->Check Out
2. You can delete the dummy file again, as it is not needed any more
3. Now we can modify the MULTICHANNELSALES calculation view by double clicking
4. On the right hand side, you see the graphical representation of the calculation view, click on
Semantics area of the calculation view, select Parameters/Variables tab
5. Add an Input parameter, by clicking on the arrow besides the plus symbol
6. Enter the following values:
Name: I_OrderChannel
Label: I_OrderChannel
Parameter Type: Direct
Default Value: Constant
Value: *
Data Type: VARCHAR
Length: 2
7. Now we have to include this Input Parameter as filter value in the projections of our
calculation view, to filter the selected order channels. Therefore, you have to double click on
the projection box “P_BillingDocumentItem” and scroll the menu down to the filters on the
right hand side Output section
8. Double click on “Expression” and add the following filter: ("OrderChannel" ='$$I_OrderChannel$$' or match("OrderChannel",'$$I_OrderChannel$$')) and
("ReturnsAmount" >0)
This filter includes three parts:
"OrderChannel" ='$$I_OrderChannel$$' if you have selected a specific order channel, then it
is used as filter
or match("OrderChannel",'$$I_OrderChannel$$') if no order channel is selected, all results
will be shown (because the default value we set constantly to *, see 6.)
and ("ReturnsAmount" >0) we only want to see order channels with positive returns
amount
9. Add analogously our expression for the existing filter on the projection “P_POSSales”,
concatenated with the AND operator:
("HasCanceledTask"!='X') and ( "OrderChannel" ='$$I_OrderChannel$$' or
match("OrderChannel",'$$I_OrderChannel$$')) and ("ReturnsAmount" > 0)
5.2.3 XS OData services Now, as the calculation view is ready for our analysis, we will create the appropriate OData services,
which we will use in the mobile app, to query the data. First we will create a sub folder under
“Server”, called “Service”. Then we will create two XS OData files and finally test them in the
browser. One service will be used to return the amount of returns by order channel, the other by
article.
1. Create sub package “Service” under the “Server” folder in the Project Explorer
2. Now create the .xsodata file: right click the new folder and select New -> XS Odata File, add
the file name “OrderChannelReturns” and click “Finish”
3. Add the following code to this file
service {
"PartnerApplications.OrderChannelAnalysis.Server.Model::MULTICHANNELSALES"
as "CalcView" with ("OrderChannel", "ReturnsAmount", "TransactionCurrency")
keys generate local "ID"
parameters via entity "InputParams";
}
- PartnerApplications.OrderChannelAnalysis.Server.Model::MULTICHANNELSA
LES
is the path to the queried calculation view
- with ("OrderChannel", "ReturnsAmount", "TransactionCurrency")
only values for OrderChannel, ReturnsAmount and TransactionCurrency shall be returned,
which is provided by the “with” parameter
- parameters via entity "InputParams";
the is parameterized by the “InputParams” argument in the URL
4. Save and activate the service
5. Test the service in your browser, by typing the following URL:
http://YOUR_IP:8002/PartnerApplications/OrderChannelAnalysis/Server/Service/OrderChannelRetur
ns.xsodata/InputParams(I_OrderChannel='*')/Results?$format=json
You should get the following result in JSON format:
6. Add analogously the second service, called “ArticleReturns.xsodata” which will provide the
detailed article information. Insert the following code into the XS Odata File, save and
activate the file
service {
"PartnerApplications.OrderChannelAnalysis.Server.Model::MULTICHANNELSALES"
as "CalcView" with ("Article", "ReturnsAmount", "TransactionCurrency")
keys generate local "ID"
parameters via entity "InputParams";
}
7. Test the service in your browser, by typing the following URL (we will get the articles
returned in the order channel with the ID ‘04’)
http://YOUR_IP:8002/PartnerApplications/OrderChannelAnalysis/Server/Service/ArticleReturns.xsod
ata/InputParams(I_OrderChannel='04')/Results?$format=json
You should get the following result in JSON format:
5.3 Web Content development In previous sections we have prepared the server side parts of the example application. Specifically,
we have copied the MultiChannelSales view, as part of SAP CAR content and modified it for our
needs. Finally, we provided two OData services, which will reuse in the following.
This chapter contains a step-by-step description of the front end implementation of the mobile
application. We will use for this example a fiori9 like, split app. The described Router based
navigation, as well as other main concepts of building UI5 applications, can be found at sap.help.com 10.
5.3.1 Folder Structure We prepare initially the folder structure for the front end development as follows.
1. Add the folder “WebContent” on the same level as “Server” in the Project Explorer
2. Add the following sub folders to the “WebContent” Folder
a. View will contain the views of the app
b. Controller will contain the appropriate controllers of the app
c. i18n will contain the message bundle file for localized texts 11
5.3.2 Index File In the first step we create and modify the index.html file, which resides in the WebContent folder of
the project. The main parts of this file will be described accordingly.
1. Create an index file and paste the following content into it, finally save and activate the file:
9 http://www.sap.com/solution/ux-user-experience/software/fiori/index.html 10 http://help.sap-ag.de/saphelp_nw74/helpdata/de/b4/d66ebee72645c1a3501a769e935541/content.htm?frameset=/de/31/a8db9d97544bb7964a6bf18e4678ef/frameset.htm¤t_toc=/de/5c/be4e5b4a19479a92b1d32ff23b7b63/plain.htm&node_id=79&show_children=false 11 http://help.sap.com/saphelp_uiaddon10/helpdata/en/91/f385926f4d1014b6dd926db0e91070/content.htm
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta charset="UTF-8">
<title>Order Channel Analysis</title>
<script
id="sap-ui-bootstrap"
src="/sap/ui5/1/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m, sap.makit"
data-sap-ui-resourceroots='{
"WebContent": "./",
"View": "./View"}' >
</script>
<script>
sap.ui.getCore().attachInit(function() {
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
height : "100%",
name : "WebContent"
})
}).placeAt("content");
});
</script>
</head>
<body class="sapUiBody" id="content">
</body>
</html>
The head element contains standard meta-information, the title of the web application and important bootstrap information in the first JavaScript tag, like the location of UI5 source files and SAP’s standard theme “bluecrystal”. Since we are building a mobile application, we use the sap.m library, as well as the sap.makit library12 for the visualization with a Pie Chart. Finally, we are defining the namespaces and locations, where the artifacts can be found, by declaring the data-sap-ui-resourceroots parameter: the root “WebContent” namespace and “./” location, and explicitly the “./View” directory, as will be used by the Component (see next section).
12https://sapui5.netweaver.ondemand.com/sdk/docs/api/symbols/sap.makit.Chart.html
<script
id="sap-ui-bootstrap"
src="/sap/ui5/1/resources/sap-ui-core.js"
data-sap-ui-theme="sap_bluecrystal"
data-sap-ui-libs="sap.m, sap.makit"
data-sap-ui-resourceroots='{
"WebContent": "./",
"View": "./View"}' >
</script>
The application will be started with sap.ui.getCore().attachInit , which will initiate an
sap.ui.core.ComponentContainer inside an sap.m.Shell (more information on component
containers you can find here13):
<script>
sap.ui.getCore().attachInit(function() {
new sap.m.Shell({
app: new sap.ui.core.ComponentContainer({
height : "100%",
name : "WebContent"
})
}).placeAt("content");
});
</script>
Finally, we are placing the shell in the body of the index.html file with placeAt("content")
referring to the id=”content” of the body element.
<body class="sapUiBody" id="content">
</body>
5.3.3 Model View Controller We will build a split app with the characteristic master and detail views. The navigation is being
handled by the routing mechanism, which will manage the aggregation behavior of the certain views.
Following strictly the Model View Controller (MVC) pattern we will start with a Component that
initiates the App view and controls the routing navigation as well as initial model binding.
The following tree summarizes the controls and MVC artifacts we will use.
13 http://help.sap.com/saphelp_nw74/helpdata/de/18/2ab413eb54433eb16f1ecf15a00651/content.htm
control:UIComponent (Component.js)
|
+-- view:App (View/App.view.xml)
|
+-- control:SplitApp
|
+-- aggregation:masterPages
| |
| +-- view:Master (View/Master.view.xml)
| |
| +-- controller: Master (Controller/Master.controller.js)
|
+-- aggregation:detailPages
|
+-- view:Detail (View/Detail.view.xml)
|
+-- controller:Detail (Controller/Detail.controller.js)
5.3.3.1 Control Flow
In the following graphic, you can find the general control flow logic of the mobile split app with a
Home view, containing the Tile collection (in this example only one Tile has been defined). Solid
arrows symbolize forward navigation, the dashed ones the backward in-app navigations. All browser
navigations are completely managed by routing mechanism of sap.ui.core.routing.Router.
SplitApp
Master
Home
Detail
Order Channel
article Detail
Article
5.3.3.2 App view
The App view will be initiated by the component. Since the split application is a container control, hence it looks pretty minimalistic.
1. Add the first XML based view to the View folder, called App.view.xml
2. Paste the following content inside, save and activate the file
<mvc:View
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true"
xmlns="sap.m">
<SplitApp id="idAppControl" />
</mvc:View>
The app view contains one single control, the sap.m.SplitApp. Further, we need no corresponding controller for this view, as all navigation and routing is provided by the Router, as described in the following.
5.3.3.3 Component
The Component is the central control artifact (see overview in 5.3.3), which initiates all child artifacts like the involved views and controllers. The Component contains besides the configuration and initialization of the Router, the instantiation of the app view, the internationalization model and data model bindings. We will describe this parts in the code in detail in the following.
1. Create an Component.js file and paste the following content into it, finally save and activate
the file:
jQuery.sap.declare("WebContent.Component");
sap.ui.core.UIComponent.extend("WebContent.Component", {
metadata : {
routing : {
config : {
viewType:"XML",
viewPath:"View",
targetAggregation:"detailPages",
clearTarget : false
},
routes : [
{
pattern: "",
name: "Home",
view:"Home",targetControl :
"idAppControl",
targetAggregation : "detailPages"
},
{
pattern : "OrderChannelOverview",
name : "Master",
view : "Master",
targetControl : "idAppControl",
targetAggregation : "masterPages",
subroutes: [
{
pattern : "{order}",
name : "Detail",
view : "Detail"
}
]
},
]
}
},
init : function(){
jQuery.sap.require("sap.ui.core.routing.History");
jQuery.sap.require("sap.m.routing.RouteMatchedHandler");
sap.ui.core.UIComponent.prototype.init.apply(this);
var oRouter = this.getRouter();
this.routeHandler = new
sap.m.routing.RouteMatchedHandler(oRouter);
oRouter.initialize();
},
createContent : function() {
// create root view
var oView = sap.ui.view({
id : "app",
viewName : "WebContent.View.App",
type : "XML",
viewData : { component : this }
});
// set i18n model
var i18nModel = new sap.ui.model.resource.ResourceModel({
bundleUrl : "i18n/messageBundle.properties"
});
oView.setModel(i18nModel, "i18n");
// Using JSON model to connect against
OrderChannelReturns.xsodata service
var sURI = '../Server/Service/OrderChannelReturns.xsodata';
var oModel = new sap.ui.model.json.JSONModel(sURI +
"/InputParams(I_OrderChannel='*')/Results?$format=json", true);
oView.setModel(oModel);
// done
return oView;
}
});
First we define our metadata, after declaration of the Component itself as an extension of
sap.ui.core.UIComponent. The metadata section contains all information, relevant for the
routing. In config section we define the View path, which is part of the previously defined resource
roots in the index.html file (see 5.3.2). Further, the routes describe our overall control structure with
the “Home” and “Master” views, as well as the “Detail” view as subroute. The aggregations are
defined by the target aggregation parameter: a view will be instantiated by the Router into the detail
part detailPages , the content of the master view will be placed into the master part
(masterPages)of the sap.m.SplitApp control.
jQuery.sap.declare("WebContent.Component");
sap.ui.core.UIComponent.extend("WebContent.Component", {
metadata : {
routing : {
config : {
viewType:"XML",
viewPath:"View",
targetAggregation:"detailPages",
clearTarget : false
},
routes : [
{
pattern: "",
name: "Home",
view: "Home",
targetControl : "idAppControl",
targetAggregation : "detailPages"
},
{
pattern : "OrderChannelOverview",
name : "Master",
view : "Master",
targetControl : "idAppControl",
targetAggregation : "masterPages",
subroutes: [
{
pattern : "{order}",
name : "Detail",
view : "Detail"
}
]
},
]
}
},
In the init function we instantiate all relevant parts of the router:
init : function(){
jQuery.sap.require("sap.ui.core.routing.History");
jQuery.sap.require("sap.m.routing.RouteMatchedHandler");
sap.ui.core.UIComponent.prototype.init.apply(this);
var oRouter = this.getRouter();
this.routeHandler = new
sap.m.routing.RouteMatchedHandler(oRouter);
oRouter.initialize();
},
Finally, we initiate the app view in the createContent function, as well as the model bindings for the
internationalization texts and data from the OData service OrderChannelReturns.xsodata.
createContent : function() {
// create root view
var oView = sap.ui.view({
id : "app",
viewName : "WebContent.View.App",
type : "XML",
viewData : { component : this }
});
2. Please create the messageBundle.properties file beneath the i18n folder and paste the
following texts into, save and it
HomeTitle=Returns Analysis
MasterTitle=Order Channel
DetailTitle=Rate of Return
In the createContent function we bind the i18nModel to the view.
// set i18n model
var i18nModel = new sap.ui.model.resource.ResourceModel({
bundleUrl : "i18n/messageBundle.properties"
});
oView.setModel(i18nModel, "i18n");
Finally we bind the data of the OData service OrderChannelReturns.xsodata as an JSON model for
calling all Order Channels, having returns that are not null (see server side section 5.2).
var sURI = '../Server/Service/OrderChannelReturns.xsodata';
var oModel = new sap.ui.model.json.JSONModel(sURI +
"/InputParams(I_OrderChannel='*')/Results?$format=json", true);
oView.setModel(oModel);
// done
return oView;
}
});
5.3.3.4 Test and status check.
We are ready now to call our application for the first time.
1. Point your browser to the following URL, to test the progress
http://YOUR_IP:8002/PartnerApplications/OrderChannelAnalysis/WebContent/index.html
The returning result shall be the split app characteristic frame, as you can see in the image below.
5.3.4 Home, Master and Detail The following section will describe the most important parts of the application views, the complete
code you can find in the Appendix of this document (chapter 6).
5.3.4.1 Overview final structure
The final structure of our simple application will look as follows, please create accordingly the missing
controller and view files of Home, Master and Detail, into the appropriate Controller and View folder.
5.3.4.2 Home
The Home view is instantiated Router, directly after initializing the split app. It contains a tile
container, with just one tile, just for sake of showing the possibility.
<TileContainer id="tile_container">
<StandardTile
id="tile_order_channel"
icon="sap-icon://chart"
title="Returns"
info="Rate of Returns"
press="tilePress"/>
</TileContainer>
When you add the Home view and controller files to the project content, will see the follow screen,
after typing the test URL into your browser
http://YOUR_IP:8002/PartnerApplications/OrderChannelAnalysis/WebContent/index.html
The Home controller has two parts the onInit function, called directly at initialization of the view
sap.ui.controller("WebContent.Controller.Home", {
onInit: function(evt) {
var oApp = sap.ui.getCore().byId("app--idAppControl");
oApp.setMode(sap.m.SplitAppMode.HideMode);
},
Here we use sap.m.SplitAppMode.HideMode to hide the master part, as it is not relevant initialy
After clicking on the Tile in the Home view the event is handled by the tilePress function, to navigate
to master view, showing the split screen. This navigation is handled by the Router, instantiated in the
home controller:
tilePress: function(evt) {
var oApp = sap.ui.getCore().byId("app--idAppControl");
var oView = this.getView();
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
var id = oView.getId();
switch (evt.oSource.getId()) {
case id + "--tile_order_channel":
oApp.setMode(sap.m.SplitAppMode.ShowHideMode);
oRouter.navTo("Master", {}, false);
With this approach one can easily add additional tiles for navigation to other views.
5.3.4.3 Master
In the master controller the onInit function we set the handler to handle routing events with
sap.ui.core.UIComponent.getRouterFor(this).attachRoutePatternMatched(this.o
nRouteMatched, this);
The certain Order Channels are represented as list items for navigation. On press event on an item
the app navigates to the Datail view, passing the selected Order Channel to the detail view, by calling
the showDetail function.
Note: here is the global view binding of the app reused, since a JSON model is used you standardly
reach content through /d/results path. In this case a template with custom formatter has been used
to show the value and the currency of the returns in the appropriate order channel.
list.bindItems({
path: "/d/results",
template: new sap.m.StandardListItem({
title: "{OrderChannel}",
description: {
parts: [{
path: 'ReturnsAmount'
}, {
path: 'TransactionCurrency'
}],
formatter: function(ra, tc) {
var text = "";
text = ra + ' ' + tc;
return text;
}
},
type: sap.m.ListType.Navigation,
press: function(evt) {
var context = evt.getSource().getBindingContext();
self.showDetail(context.getProperty().OrderChannel);
}
}).data("OrderChannel", "{OrderChannel}")
});
},
In the showDetail function we navigate to the detail view, passing the chosen item, hence Order
Channel.
showDetail: function(oItem) {
sap.ui.core.UIComponent.getRouterFor(this).navTo("Detail", {
from: "Master",
order: oItem
})
}
5.3.4.4 Detail
The detail view we use to initially show the rate of returns by the appropriate order channels in
a Pie Chart from the sap.makit library. This will look like the following image, when we finally
save and activate the detail view and controller file (you will find the complete code in the
Appendix, in chapter 6).
As described in the previous section, discussing the master controller, we route to the detail
view, with the chosen order channel on the left hand side, to see the rate of returns drilled
down by the certain articles. Therefore the previously a new JSON model is binded to the Pie
Chart, showing the incorporated articles and their share of the returns in the channel.
When we choose Order Channel 06 for instance, we will see the following detail view, showing
the rate of returns by the articles being returned in this Order Channel.
In the onInit function we declare the oCenterBox object, which is a sap.m.FlexBox containing
the Pie Chart. Further, the oHeader object to dynamically change the title of the ObjectHeader.
Finally, we set the handler to handle routing events, to the master controller.
onInit: function() {
// create container for chart
this.oCenterBox = this.getView().byId("centerBox");
this.oHeader = this.getView().byId("header");
sap.ui.core.UIComponent.getRouterFor(this).attachRoutePatternMatched(this.o
nRouteMatched, this);
}
The relevant view objects, instantiated above are defined in the Page tag of the detail view
XML:
<Page
title="{i18n>DetailTitle}"
showNavButton="true"
navButtonPress="handleNavButtonPress" >
<ObjectHeader
id="header" ></ObjectHeader>
<FlexBox id="centerBox"
fitContainer = "true"
justifyContent = "Center"
alignItems = "Center"></FlexBox>
</Page>
As mentioned in the chapter introduction, we rebind the model for the chart, each time the
context changes, by passing the Order Channel ID to the appropriate OData service. When we
route, to the detail view, the onRouteMatched function is called. Depending on the route we
get whether the overview or a certain order channel in oParameters.arguments.order
parameter. In case of overview we would like to see the rate of returns by order channel,
therefore we call the OrderChannelReturns.xsodata service and bind it to our view model.
Then, we set the title accordingly and call the renderChart function with appropriate binding
parameter {OrderChannel}.
onRouteMatched: function(oEvent) {
var oParameters = oEvent.getParameters();
if (this.oCenterBox.getItems().length > 0) {
this.oCenterBox.destroyItems();
}
var oView = this.getView();
if (oParameters.arguments.order === "OrderChannelOverview") {
var sURI = '../Server/Service/OrderChannelReturns.xsodata';
var oModel = new sap.ui.model.json.JSONModel(sURI +
"/InputParams(I_OrderChannel='*')/Results?$format=json", true);
oView.setModel(oModel);
this.oHeader.setTitle('Order Channel Overview');
this.renderChart("{OrderChannel}");
Analogously, we call the ArticleReturns.xsodata service in case of specific order channel,
set the title and call the renderChart function with appropriate binding parameter {Article}.
} else {
var orderChannel = oParameters.arguments.order;
var sURI = '../Server/Service/ArticleReturns.xsodata';
var oModel = new sap.ui.model.json.JSONModel(sURI +
"/InputParams(I_OrderChannel='" + orderChannel + "')/Results?$format=json",
true);
oView.setModel(oModel);
this.oHeader.setTitle('By Article in Order Channel ' +
orderChannel);
this.renderChart("{Article}");
}
In case of the in app navigation, we handle the push button event of the detail view as follows
handleNavButtonPress: function(evt) {
if (this.oHeader.getTitle() === "Order Channel Overview") {
var oApp = sap.ui.getCore().byId("app--idAppControl");
oApp.setMode(sap.m.SplitAppMode.HideMode);
sap.ui.core.UIComponent.getRouterFor(this).navTo("Home", {
from: "Master"
})
} else {
sap.ui.core.UIComponent.getRouterFor(this).navTo("Master", {
from: "Detail"
})
}
}
In case of the overview, we would like to navigate to the home view. Otherwise, from the
specific order channel, showing article relate share of returns we would like to get back to order
channel overview (compare 5.3.3.1 Control Flow overview).
6 Appendix This chapter contains the complete code for the remaining of Home, Master and Detail views and
controllers, which you can paste into the according files.
6.1 Home view
<mvc:View
height="100%"
controllerName="WebContent.Controller.Home"
xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core"
xmlns="sap.m">
<Page
showHeader="true"
enableScrolling="false"
title="{i18n>HomeTitle}" >
<TileContainer id="tile_container">
<StandardTile
id="tile_order_channel"
icon="sap-icon://chart"
title="Returns"
info="Rate of Returns"
press="tilePress"/>
</TileContainer>
</Page>
</mvc:View>
6.2 Home controller
sap.ui.controller("WebContent.Controller.Home", {
onInit: function(evt) {
var oApp = sap.ui.getCore().byId("app--idAppControl");
oApp.setMode(sap.m.SplitAppMode.HideMode);
},
tilePress: function(evt) {
var oApp = sap.ui.getCore().byId("app--idAppControl");
var oView = this.getView();
var oRouter = sap.ui.core.UIComponent.getRouterFor(this);
var id = oView.getId();
switch (evt.oSource.getId()) {
case id + "--tile_order_channel":
oApp.setMode(sap.m.SplitAppMode.ShowHideMode);
oRouter.navTo("Master", {}, false);
break;
default:
alert(evt.oSource.getId());
}
}
});
Master view
<core:View
controllerName="WebContent.Controller.Master"
xmlns="sap.m"
xmlns:core="sap.ui.core" >
<Page
title="{i18n>MasterTitle}"
>
<subHeader>
<Bar>
<contentLeft>
<SearchField
search="handleSearch"
width="100%" >
</SearchField>
</contentLeft>
</Bar>
</subHeader>
<List
id="list"
mode="{device>/listMode}"
selectionChange="handleListSelect">
</List>
</Page>
</core:View>
6.3 Master controller
sap.ui.controller("WebContent.Controller.Master", {
onInit: function(evt) {
var list = this.getView().byId("list");
var self = this;
sap.ui.core.UIComponent.getRouterFor(this).attachRoutePatternMatched(this.o
nRouteMatched, this);
list.bindItems({
path: "/d/results",
template: new sap.m.StandardListItem({
title: "{OrderChannel}",
description: {
parts: [{
path: 'ReturnsAmount'
}, {
path: 'TransactionCurrency'
}],
formatter: function(ra, tc) {
var text = "";
text = ra + ' ' + tc;
return text;
}
},
type: sap.m.ListType.Navigation,
press: function(evt) {
var context = evt.getSource().getBindingContext();
self.showDetail(context.getProperty().OrderChannel);
}
}).data("OrderChannel", "{OrderChannel}")
});
},
onRouteMatched: function(oEvent) {
var sName = oEvent.getParameter("name");
if (sName !== "Main") {
return;
}
},
handleSearch: function(evt) {
// create model filter
var filters = [];
var query = evt.getParameter("query");
if (query && query.length > 0) {
var filter = new sap.ui.model.Filter("OrderChannel",
sap.ui.model.FilterOperator.Contains, query);
filters.push(filter);
}
// update list binding
var list = this.getView().byId("list");
var binding = list.getBinding("items");
binding.filter(filters);
},
showDetail: function(oItem) {
sap.ui.core.UIComponent.getRouterFor(this).navTo("Detail", {
from: "Master",
order: oItem
})
}
});
6.4 Detail view
<core:View
controllerName="WebContent.Controller.Detail"
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
xmlns:core="sap.ui.core"
xmlns:l="sap.ui.layout">
<Page
title="{i18n>DetailTitle}"
showNavButton="true"
navButtonPress="handleNavButtonPress" >
<ObjectHeader
id="header" ></ObjectHeader>
<FlexBox id="centerBox"
fitContainer = "true"
justifyContent = "Center"
alignItems = "Center"></FlexBox>
</Page>
</core:View>
6.5 Detail controller
sap.ui.controller("WebContent.Controller.Detail", {
onInit: function() {
// create container for chart
this.oCenterBox = this.getView().byId("centerBox");
this.oHeader = this.getView().byId("header");
sap.ui.core.UIComponent.getRouterFor(this).attachRoutePatternMatched(this.o
nRouteMatched, this);
},
onRouteMatched: function(oEvent) {
var oParameters = oEvent.getParameters();
if (this.oCenterBox.getItems().length > 0) {
this.oCenterBox.destroyItems();
}
var oView = this.getView();
if (oParameters.arguments.order === "OrderChannelOverview") {
var sURI = '../Server/Service/OrderChannelReturns.xsodata';
var oModel = new sap.ui.model.json.JSONModel(sURI +
"/InputParams(I_OrderChannel='*')/Results?$format=json", true);
oView.setModel(oModel);
this.oHeader.setTitle('Order Channel Overview');
this.renderChart("{OrderChannel}");
} else {
var orderChannel = oParameters.arguments.order;
var sURI = '../Server/Service/ArticleReturns.xsodata';
var oModel = new sap.ui.model.json.JSONModel(sURI +
"/InputParams(I_OrderChannel='" + orderChannel + "')/Results?$format=json",
true);
oView.setModel(oModel);
this.oHeader.setTitle('By Article in Order Channel ' +
orderChannel);
this.renderChart("{Article}");
}
},
renderChart: function(detail) {
// Pie Chart
var oChart = new sap.makit.Chart({
width: "700px",
height: "500px",
type: sap.makit.ChartType.Pie,
legendPosition: sap.makit.LegendPosition.Right,
valueAxis: new sap.makit.ValueAxis({}),
categoryAxis: new sap.makit.CategoryAxis({}),
category: new sap.makit.Category({
column: "channel",
}),
values: [new sap.makit.Value({
expression: "return",
format: "number",
})],
});
oChart.addColumn(new sap.makit.Column({
name: "channel",
value: detail
}));
oChart.addColumn(new sap.makit.Column({
name: "return",
value: "{ReturnsAmount}",
type: "number"
}));
oChart.bindRows({
path: "/d/results"
});
this.oCenterBox.addItem(oChart);
},
handleNavButtonPress: function(evt) {
if (this.oHeader.getTitle() === "Order Channel Overview") {
var oApp = sap.ui.getCore().byId("app--idAppControl");
oApp.setMode(sap.m.SplitAppMode.HideMode);
sap.ui.core.UIComponent.getRouterFor(this).navTo("Home", {
from: "Master"
})
} else {
sap.ui.core.UIComponent.getRouterFor(this).navTo("Master", {
from: "Detail"
})
}
}
});
© 2015 SAP SE or an SAP affiliate company. All rights reserved. No part of this publication may be reproduced or transmitted in any form or for any purpose without the express permission of SAP SE or an SAP affiliate company. SAP and other SAP products and services mentioned herein as well as their respective logos are trademarks or registered trademarks of SAP SE (or an SAP affiliate company) in Germany and other countries. Please see http://www.sap.com/corporate-en/legal/copyright/index.epx#trademark for additional trademark information and notices. Some software products marketed by SAP SE and its distributors contain proprietary software components of other software vendors. National product specifications may vary. These materials are provided by SAP SE or an SAP affiliate company for informational purposes only, without representation or warranty of any kind, and SAP SE or its affiliated companies shall not be liable for errors or omissions with respect to the materials. The only warranties for SAP SE or SAP affiliate company products and services are those that are set forth in the express warranty statements accompanying such products and services, if any. Nothing herein should be construed as constituting an additional warranty. In particular, SAP SE or its affiliated companies have no obligation to pursue any course of business outlined in this document or any related presentation, or to develop or release any functionality mentioned therein. This document, or any related presentation, and SAP SE’s or its affiliated companies’ strategy and possible future developments, products, and/or platform directions and functionality are all subject to change and may be changed by SAP SE or its affiliated companies at any time for any reason without notice. The information in this document is not a commitment, promise, or legal obligation to deliver any material, code, or functionality. All forward-looking statements are subject to various risks and uncertainties that could cause actual results to differ materially from expectations. Readers are cautioned not to place undue reliance on these forward-looking statements, which speak only as of their dates, and they should not be relied upon in making purchasing decisions.
www.sap.com