Quantcast
Channel: SAPUI5 Developer Center
Viewing all 789 articles
Browse latest View live

FIORI: Setting up Eclipse Luna when SAP Web IDE on HCP and on-premise cannot be used

$
0
0

OS: Windows 7 Professional

System Type: 32-bit operating system

 

Restrictions:

1. Cannot use SAP Web IDE on HANA Cloud Platform due to a highly secured network. Cloud technology or connection to internet not allowed

2. Cannot use SAP Web IDE on-premise (local installation) due to system type: 32-bit operating system


Solution: Use Eclipse Luna for Fiori, SAPUI5 and OData service development

 

Installation procedure

1. Download Java version 7

2. Remove other version of Java and Instal Java version 7 (1.7)

3. Perform a new Eclipse installation in your system - Eclipse Java EE Luna SR2

Note: If the installation is not completely new, the toolkit installation will fail because of clashing Graphiti versions.  Add an additional update site for the Graphiti plugin before starting the installation.

 

4. Download Eclipse Graphiti for Juno release 0.9.1

5. From the menu bar, choose Help > Install new software. The Available Software page is displayed.

6. Click Add. The Add Repository page is displayed.

7. In the Name field, enter a name for the Graphiti plugin.

8. In the Location field, enter http://archive.eclipse.org/graphiti/updates/0.9.1 or Browse for the download graphiti ZIP file and click OK.

9. Select the Contact all update sites during install to find required software checkbox.

10. After the installation restart eclipse.

11. Then next is the HANA tools update site To add the update site:

12. Start Eclipse.

13. From the menu bar, choose Help > Install new software. The Available Software page is displayed.

14. Click Add. The Add Repository page is displayed.

15. In the Name field, enter a name for the repository.

16. In the Location field, enter https://tools.hana.ondemand.com/juno

17. Click OK.

18. Select the UI Development Toolkit for HTML5 checkbox

19. Select the Contact all update sites during install to find required software checkbox.

20. After the installation restart eclipse.

21. You must download the SAP Fiori toolkit installation file available at the SAP Developer Network site: SAP Fiori toolkit installation zip

22. Start Eclipse.

23. From the menu bar, choose Help > Install new software. The Available Software page is displayed.

24. Click Add. The Add Repository page is displayed.

25. In the Name field, enter a name for the repository.

26. In the Location field, search for the SAP Fiori toolkit ZIP Archive file

27. Click OK.

28. Select All the SAP Fiori toolkit

29. Select the Contact all update sites during install to find required software checkbox.

30. After the installation restart eclipse.

31. Start Eclipse.

32. From the menu bar, choose Help > Install new software. The Available Software page is displayed.

33. Click Add. The Add Repository page is displayed.

34. In the Name field, enter a name for the repository.

35. In the Location field, enter https://tools.hana.ondemand.com/juno

36. Click OK.

37. Select the GWPA - SAP Netweaver Gateway Productivity Accelerator

38. Select the ABAP Development Tools for SAP Netweaver

39. Select the Contact all update sites during install to find required software checkbox.

40. After the installation restart eclipse.

 

Eclipse Luna using SAP Fiori toolkit should now be working


sap.m.Table - Conditional Cell Coloring based on value

$
0
0

Hello All,

 

Introduction:

 

The blog Coloring Table Cells Conditionally in SAP UI5 clearly explains you how to color the cells of a table(sap.ui.table.Table) precisely and with neat explanation. But in case of sap.m.Table, it can't be followed because:

 

     1. sap.ui.table.Table uses bindRows method to bind the table rows.

     2. And hence the blog uses getRows method to add style classes conditionally.

 

         For Example : oTable.getRows()[i].$().removeClass("yellow"); 

 

     3. sap.m.Table doesn't use bindRows method to bind the rows. It is based on "items".

 

Step by Step Process:

 

Create a SAP UI5 project with sap.m library and with an initial view.

 

index.html looks like below:

 

<!DOCTYPE HTML><html>  <head>  <meta http-equiv="X-UA-Compatible" content="IE=edge">  <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>  <script src="resources/sap-ui-core.js"
 id="sap-ui-bootstrap"
 data-sap-ui-libs="sap.m"
 data-sap-ui-theme="sap_bluecrystal">  </script>  <!-- only load the mobile lib "sap.m" and the "sap_bluecrystal" theme -->  <script>
 sap.ui.localResources("zmtablecolor");  var app = new sap.m.App({initialPage:"idinitialview1"});  var page = sap.ui.view({id:"idinitialview1", viewName:"zmtablecolor.initialview", type:sap.ui.core.mvc.ViewType.JS});  app.addPage(page);
 app.placeAt("content");  </script>  </head>  <body class="sapUiBody" role="application">  <div id="content"></div>  </body></html>

 

 

 

view looks like below:

 

*Add oController.createPage() inside the sap.m.Page function; because that will create and return the table *

 

 

 

 

sap.ui.jsview("zmtablecolor.initialview", {  /** Specifies the Controller belonging to this View.  * In the case that it is not implemented, or that "null" is returned, this View does not have a Controller.  * @memberOf zmtablecolor.initialview  */  getControllerName : function() {  return "zmtablecolor.initialview";  },  /** Is initially called once after the Controller has been instantiated. It is the place where the UI is constructed.  * Since the Controller is given to this method, its event handlers can be attached right away.  * @memberOf zmtablecolor.initialview  */  createContent : function(oController) {  return new sap.m.Page({  title: "M Table Colouring",  content: [
 oController.createPage()  ]  });  }
});

 

 

 

 

Content Creation:

 

create a method "createPage" in the controller as shown below:

 

createPage: function() {  jsonData = [];  jsonData.push({  "Invoice" : "INV1",  "Amount" : 123  });  jsonData.push({  "Invoice" : "INV2",  "Amount" : 84  });  jsonData.push({  "Invoice" : "INV3",  "Amount" : 283  });  var oInvoicesTable = new sap.m.Table("idInvoicesTable", {  //width: tabWidth,  fixedLayout: false,  width : '30%',  growing : true,  inset : true,  headerText : "My Invoice Details",  growingScrollToLoad : true,  columns: [                          
 new sap.m.Column({
 //width: "40%",
 header: new sap.m.Text({
 text: "Invoice"
 })
 }),             
 new sap.m.Column({
 //width: "30%",
 header: new sap.m.Text({
 text: "Amount"
 })
 }),                           ],      
 items : {
 path: '/modelData',
 template: new sap.m.ColumnListItem({
 selected: false,
 //type: "Active",
 cells: [
 new sap.m.Text("idColInvoice", {
 text: "{Invoice}"
 }),
 new sap.m.Text("idColAmount", {
 text: "{Amount}"
 }),               
 ]
 })
 }}).addStyleClass('sapUiSizeCompact');  var oInvoicesMdl = new sap.ui.model.json.JSONModel();  oInvoicesMdl.setData({modelData : jsonData});
 oInvoicesTable.setModel(oInvoicesMdl);  return oInvoicesTable;  }

 

 

 

 

Now save and run the application; It will show you output as below:

 

tablewo.png

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Now, let us see how to color the cell based on below condition:

 

If amount is less than 100, make it RED.

If amount is greater than or equal to 100 and less than 200, make it YELLOW.

If amount is greater than or equal to 200, make it GREEN.

 

CSS Styling:

 

  1. 1. create a CSS file under webcontent->css folder and name it as style.css(as you wish).
  2. 2. Paste the below content inside it. This is responsible for coloring the cell.

 

.green {
 background-color: #66FF33;
}
.red {
 background-color: #FF3300;
}
.yellow {
 background-color: #FFFF66;
}

 

 

     3. Insert below tag in index.html file.

 

    

<link rel="stylesheet" href="css/style.css">

 

 

 

Conditional Formatting:

 

     4. Inside the onAfterRendering function of the controller, we need to write logic to color the cells based on values. It should look like below:

 

onAfterRendering: function() {
var tabData = sap.ui.getCore().byId("idInvoicesTable").getModel().getData().modelData;  var tabDataLength = tabData.length;  var colId = "";  var colValue = "";  for(var i =0; i<tabDataLength; i++){  colId = "idColAmount-__clone" + i;  colValue = sap.ui.getCore().byId(colId).getText();  colValue = parseInt(colValue);  if(colValue < 100){
 sap.ui.getCore().byId(colId).addStyleClass("red");
 sap.ui.getCore().byId(colId).removeStyleClass("green");
 sap.ui.getCore().byId(colId).removeStyleClass("yellow");  }else if(colValue >= 100 && colValue < 200){
 sap.ui.getCore().byId(colId).addStyleClass("yellow");
 sap.ui.getCore().byId(colId).removeStyleClass("red");
 sap.ui.getCore().byId(colId).removeStyleClass("green");  }else if(colValue >= 200){
 sap.ui.getCore().byId(colId).addStyleClass("green");
 sap.ui.getCore().byId(colId).removeStyleClass("yellow");
 sap.ui.getCore().byId(colId).removeStyleClass("red");  }  }

 

 

That's it. We are done. Now, the output looks like:


tablew.png

 

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

Explanation of the above logic:

 

By this time, you would have understood how it has been achieved. Nevertheless, I will explain the logic - which we have applied in the onAfterRendering function of the controller.

 

 

 

     a. Make sure ID has been assigned to the corresponding cell of the table as shown below. Then only the ID is static and known to us definitely.

     you can refer method "createPage" given above.

 

new sap.m.Text("idColAmount", {
 text: "{Amount}"
 }),

 

 

     b. So once the table is rendered,

 

     the Amount cell of first row is "idColAmount-__clone0"

     the Amount cell of first row is "idColAmount-__clone1" and so on.

 

     So we need to iterate the values based on the data bound to the table.

 

     c. get the data bound to the table.

 

var tabData = sap.ui.getCore().byId("idInvoicesTable").getModel().getData().modelData;
var tabDataLength = tabData.length;

     d. Inside the loop, we need to check the condition. We need to fix the ID based on the index and Make sure that the text is converted into integer using      function parseInt() for proper check.

 

colId = "idColAmount-__clone" + i;  colValue = sap.ui.getCore().byId(colId).getText();  colValue = parseInt(colValue);

     e. Now use addStyleClass method to assign a class and remove other classes using removeStyleClass function, to make sure only once class is assigned      at a time.

 

 

if(colValue < 100){
 sap.ui.getCore().byId(colId).addStyleClass("red");
 sap.ui.getCore().byId(colId).removeStyleClass("green");
 sap.ui.getCore().byId(colId).removeStyleClass("yellow");  }





Thank you. Appreciate your comments.

 

Seyed Ismail.

UI5 offline application using AppCache and LocalStorage

$
0
0

This project demonstrates how to develop an offline enabled OpenUI5 stock application using the AppCache API and LocalStorage. The app is stored inside the browser and does not need a native shell to be offline enabled.

 

You can try it out here:

https://pensoffsky.github.io/OpenUI5-AppCache/index.html

 

Sources:

GitHub - pensoffsky/OpenUI5-AppCache

 

 

Features

The app is able to run offline in all current browsers. It implements a very basic stock application. The last fetched data is persisted in the browser and even in airplane mode the app is reachable and will display the last fetched stock quotes.

 

 

Concepts

AppCache for UI5 & app resources

The manifest.appcache file defines which resources shall be stored in the browser for offline usage.

 

 

    CACHE MANIFEST    resources/sap-ui-core.js    resources/sap/m/library-preload.json    resources/sap/ui/core/library-preload.json    resources/sap/ui/thirdparty/jquery-mobile-custom.js    resources/sap/ui/core/themes/sap_bluecrystal/library.css    resources/sap/m/themes/sap_bluecrystal/library.css    resources/sap/ui/core/messagebundle_en.properties    resources/sap/m/messagebundle_en.properties    resources/jquery.sap.storage.js    resources/sap/ui/core/themes/base/fonts/SAP-icons.ttf    resources/sap/ui/core/themes/sap_bluecrystal/library-parameters.json    resources/sap/m/themes/sap_bluecrystal/library-parameters.json    resources/sap/ui/thirdparty/unorm.js    resources/sap/ui/thirdparty/unormdata.js    resources/sap/ui/core/themes/base/fonts/SAP-icons.eot    de.pensware.ui5StocksApp/Component.js    de.pensware.ui5StocksApp/manifest.json    de.pensware.ui5StocksApp/view/Main.view.xml    de.pensware.ui5StocksApp/view/Main.controller.js    de.pensware.financeAPI/Component.js    de.pensware.financeAPI/js/stockQuotesAPI.js    NETWORK:    *

Everything below CACHE MANIFEST defines all the OpenUI5 and app resources needed to run the app. All these files are fetched on the first start of the app and are then available for offline usage. **NETWORK: *** means that every network request not specified in CACHE MANIFEST will be sent directly to the network.

 

 

Component based design

The code related to fetching the stock quotes from yahoo is encapsulated into a faceless component.

This financeAPI component is loaded with the following code:

 

var ofinanceAPI = sap.ui.component( {name: "de.pensware.financeAPI" } )
var oStockQuotesAPI = ofinanceAPI.getStockQuotesAPI();

 

LocalStorage to persist data

Stock symbols and fetched data from yahoo finance api are stored in local storage for offline usage.

 

 

Model View Controller + light weight ViewModel

The Main.view.xml is XML format. The Main.controller.js instantiates a JSONModel and sets it with the name "localUIModel" to the view.

 

_createAndSetLocalUIModel : function () {  this._localUIModel = new sap.ui.model.json.JSONModel();  this._localUIModel.setData({  symbols: [{symbol: "test", price: "489"}, {symbol: "MSFT", price: ""}],  newSymbol: "",  aMessages: [],  listMode: sap.m.ListMode.None  });  this.getView().setModel(this._localUIModel, "localUIModel");
}

Every input the user makes or data the app wants to display is written into this model. This way the Main.controller.js makes no assumptions on how the data is displayed and the Main.view.xml can be changed without having to change javascript code.

 

This also makes the controller testable. An event handler like onToggleListMode is only modifying the "localUIModel" and that can be tested very easily.

 

onToggleListMode : function () {  var sCurrentMode = this._localUIModel.getProperty("/listMode");  if (sCurrentMode === sap.m.ListMode.None) {  this._localUIModel.setProperty("/listMode", sap.m.ListMode.Delete);  } else {  this._localUIModel.setProperty("/listMode", sap.m.ListMode.None);  }
}

 

The test:

QUnit.test("onToggleListMode function", function (assert) {  var oLocalUIModelData = this._oCntrllr._localUIModel.getData();  //initial mode is sap.m.ListMode.None  assert.equal(oLocalUIModelData.listMode, sap.m.ListMode.None);  this._oCntrllr.onToggleListMode();  assert.equal(oLocalUIModelData.listMode, sap.m.ListMode.Delete);  this._oCntrllr.onToggleListMode();  assert.equal(oLocalUIModelData.listMode, sap.m.ListMode.None);
});

 

Injecting dependencies into controller for better testability

The stockquotes API object and the storage object are injected into the Main.controller.

This way the Main.controller can be instantiated with a mock version of the stockquotes API object for easy unit testing.

var oStockQuotesAPI = {  fetchData: function () {  return {  fail: function () {}  }  }
};
var oStorage = jQuery.sap.storage(jQuery.sap.storage.Type.session);
this._oCntrllr = new de.pensware.ui5StocksApp.view.Main(oStockQuotesAPI, oStorage);

Auto Language Conversion : Google Translate + UI5

$
0
0

Its really awesome when it comes to the possibilities that SAP UI5 offers.

SAP UI5 has the capability to provide translatable texts SAPUI5 SDK - Demo Kit .

But the problem is you have to maintain the property/resource file for each and every language along with the text.

Although it is recommended from the quality & stability point of view , it includes a lot of manual effort.

 

What is the solution?

     Nowadays  you have google website translator which helps in translating your website without any effort.

    Website Translator

 

How it Works ?

     Google translator detects each and every div(inner HTML/ text) and send a post query which fetches the translated text and applies to the respective div.

     Since UI5 internally renders all the controls as HTML Div s , it is supposed to work with UI5 as well.

 

How do i implement ?

   




Step 1     :  Call the google translate JS file and initiate (in side HTML Header)

              

<script type="text/javascript" src="//translate.google.com/translate_a/element.js?cb=googleTranslateElementInit"></script><script type="text/javascript">        var userLang = navigator.language || navigator.userLanguage || navigator.languages;         if (userLang.substr(0,2) != "en"){          function googleTranslateElementInit() {            new google.translate.TranslateElement({pageLanguage: 'en', layout:             google.translate.TranslateElement.FloatPosition.TOP_LEFT}, 'google_translate_element');           }         }        else {           document.getElementById("google_translate_element").style.display="none";          }</script>

   



Step 2   :        Now a default header will be applied by google, now to hide it insert the following css code snippet

 

            

<style type="text/css">iframe.goog-te-banner-frame{ display: none !important;}</style><style type="text/css">body {position: static !important; top:0px !important;}</style>

 


Step 3 :       Next we have to trigger the post based on the browser language.

                    To detect browser language you can use sap.ui.getCore().getConfiguration().getLanguage()

                    I have placed the function under the onAfterRendering life-cycle event which will be triggered after a delay of 3 second.

 

onAfterRendering:function(){        function changeLanguage() {            var jObj = $('.goog-te-combo');             var db = jObj.get(0);             var lang = sap.ui.getCore().getConfiguration().getLanguage()             jObj.val(lang);             var evt = document.createEvent("HTMLEvents");             evt.initEvent('change', true, true );
//             jObj.dispatchEvent(evt);             db.dispatchEvent(evt);        }                 setTimeout(changeLanguage, 3000)    },

Get Set Go >>>

Now everything is done and the ui5 app will detect the browser language and change the text accordingly.

 

How do i test it ?


     1.You can go to the browser and change the language settings.

     2. After the URI you can add a parameter ?sap-ui-language=de

 

    

Amazingly it gives a pretty accurate results for over 100+ languages , but sometimes the wordings may not have the proper context meaning

 

Results


German

 

Russian


Hindi

 

French

 

 

Hope the post is useful .

Thanks

How to create UI5 application for success factor in HCP webIde

Creating hierarchical data using Content-ID Referencing in a Change Set (Batch Request) in hybrid application

$
0
0

There is a limitation in OData specifications that does not allow deep inserts 1:N for Offline applications.  However, you can use Content-ID referencing in a Change Set (batch request) to overcome this limitation.  Please refer to the OData specifications on Referencing Requests in a Change Set.  Note that the OData producer must support Content-ID referencing in order for this to work.

 

In our example, we will use the universally available OData Service found in http://services.odata.org.  Since this involves updating the backend data, use the link to create a full access (Read-Write) service.  The OData Service should look something similar to this.  http://services.odata.org/(S(i01sargg1imht0wuq102ghz1))/V2/OData/OData.svc/.  The OData version must be V2 and note the placement of the V2 string in the URL.

 

Note:  SAP Gateway 740 SP13 and above supports Content-ID referencing.  SAP Gateway 2.0 SP12 is also scheduled to support Content-ID referencing.  However, it is recommended to use the newer SAP Gateway 740 SP13 or above.

Difference between deep insert and Content-ID referencing in a change set (batch request) ?

There are quite a few similarities between deep insert and Content-ID referencing in a change set (batch request).  Both these approaches can be used to insert hierarchical data.  The table below describes some of the differences between deep insert and Content-ID referencing in a change set (batch request).

 

Deep Insert

Content-ID referencing in a change set (batch request)

Deep insert allows creating hierarchical data using a single payload in a single request

Multiple requests are grouped into a single request

Deep Insert is somewhat easier. The single payload in the POST request is in the same format as that of a GET request with $expand

If a MIME part representing an Insert request within a ChangeSet includes a Content-ID header, then the new entity represented by that part may be referenced by subsequent requests within the same ChangeSet by referring to the Content-ID value prefixed with a “$” character.

Most OData providers support deep insert – including Integration Gateway

Integration Gateway does not support Content-ID referencing in a batch request.  However, there are other 3rd party OData producers that support Content-ID referencing in a change set.

Limitation in OData specification does not allow for deep inserts 1:N for Offline applications

No such limitation. Hierarchical data can be inserted in both Online and Offline applications

 

 

Setting up the application definition in HCPms

Setting up the application definition in HCPms is fairly straightforward.  The publicly available OData Service does not require any authentication. To keep things simple, the application definition will also not have any authentication.  I have included a few screenshots on how to set up the application definition in HCPms.

 

Application ID

com.sap.batch

Name

Content ID referencing

Type

Hybrid

Description

Content ID referencing

Vendor

SAP

Security Configuration

None (not recommended)

Back-End URL

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/

Proxy Type

Internet

Authentication

No authentication (not recommended)

 

batch1.png

 

batch2.png

 

Application Configuration file

 

[endpoint]

name=com.sap.batch

prepopulate_offline_db=Y

content_id_header_location=operation

 

 

batch3.png

 

Note:  The application configuration file is used to let HCPms know the location of the Content-ID.  This is because a lot of OData providers (including the OData Service that is being used in this blog) incorrectly requires the Content-ID as part of the operation header.  SAP Gateway correctly requires the Content-ID as part of the MIME header.  So if you are using SAP Gateway, then you would use the value ‘mime’ instead of ‘operation’.

Creating hierarchical data with 1:N relationship using Content-ID referencing in a Change Set (batch request)

The code to submit the Content-ID referencing is the same for both Online and Offline Stores.  The first step is to create the body of the request object that contains the parent and the child entities.  We will create 1 parent entity (Categories) and 2 child entities (Products).   Note that the child entities use the Content-ID (requestUri: "$1/Products") to reference the parent entity.

 

The request object is then created using the POST method.  The $batch is appended to the request URI (requestUri: getEndPointURL() + "/$batch") since this is a batch request.

 

function batchRequest() {

        var oHeaders = {

        };

 

var params = {

__batchRequests: [{

__changeRequests: [{

                    requestUri: getEndPointURL() + "/Categories",

method: "POST",

headers: {

"Content-ID": "1"

},

data: {

"ID": 5,

                        "Name": "Toys"

}

                },

                {

requestUri: "$1/Products",

method: "POST",

data: {

"Description": "UBS ChessMaster Software",

"DiscontinuedDate": "2013-01-01T00:00:00",

"ID": 510,

"Name": "ChessMaster 10th Edition",

"Price": "5.6",

"Rating": 5,

"ReleaseDate": "2010-01-01T00:00:00"

}

                },

                {

requestUri: "$1/Products",

method: "POST",

data: {

"Description": "Lego Blocks",

"DiscontinuedDate": "2013-01-01T00:00:00",

"ID": 511,

"Name": "Hasbro Ltd",

"Price": "23.50",

"Rating": 4,

"ReleaseDate": "2010-01-01T00:00:00"

}

                }

                ]

            }

            ]

        };

 

        oHeaders['Authorization'] = authStr;

 

        var request = {

headers: oHeaders,

requestUri: getEndPointURL() + "/$batch",

method: "POST",

            data: params

        };

 

OData.request(request, responseCallback, errorCallback, OData.batchHandler);

    }

 

Running the application (Online)

Running the application in Online mode is simple.  After you Onboard successfully, click on the Read button.  You should see 9 entries for the Products table.

 

batch4.png

 

Browse to the OData Service to confirm there are 9 entries for Products as well…  Also confirm there are 3 entries for Categories.

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

 

Click on the Batch request – Insert button.  This should submit both the Parent and the Child entities to the backend.  Click on Read button and notice there are 11 entries for the Product table.

 

batch5.png

 

Browse to the OData Service to confirm there are 11 entries for Products as well…  Also confirm there are 4 entries for Categories.

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

 

Note:  Since we are hard-coding the ID values, you cannot insert the same values again.

 

Running the application (Offline)

Running the application in Offline mode is simple as well.  After you Onboard successfully, you must open the Offline Store.  After the Offline Store is opened (the status will indicate that it is opened), click on Read.

 

batch6.png

 

Browse to the OData Service to confirm there are 9 entries for Products as well…  Also confirm there are 3 entries for Categories.

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

 

Click on the Batch request – Insert button.  This should submit both the Parent and the Child entities to the local Offline Store. Click on Read button and notice there are 11 entries for the Product table.  Note:  The relationship is established between the Parent and the Child entities because we are using Content-ID referencing when performing the insert.

 

batch7.png

 

Browse to the OData Service to confirm there are only 9 entries for Products.  This is because the insert was done against the local Offline Store only.  Also confirm there are 3 entries for Categories.

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

 

 

Click on Flush Store. After flush is complete (status will indicate that flush is complete), click on Read.  You will notice that there are still 11 entries for the Products table.  Behind the scenes, the new rows have now been sent to the backend.

 

batch8.png

 

Browse to the OData Service to confirm there are 11 entries for Products as well…  Also confirm there are 4 entries for Categories.

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Products/$count

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories

 

http://services.odata.org/(S(rt5puvtqg2ax2ka2tepwsonq))/V2/OData/OData.svc/Categories/$count

 

Additionally, you can also click on Refresh Store.  Note:  Since we are hard-coding the ID values, you cannot insert the same values again.

 

Viewing contents of the Offline Store (Optional)

Starting with SAP Mobile Platform SDK SP11, a utility called iLoData.exe is shipped along with the installation files.  This utility is useful for reading the contents of the Offline Store.  In addition, this utility can be used for performing CUD operations as well.  Flush and Refresh can also be executed using this utility.

 

  • Browse to the <Install Media>\modules\OfflineODataTools folder. There is a zip file named OfflineODataTools.zip.  Unzip the file to extract iLoData.exe.
  • Copy the Offline Store UDB files.  For Windows hybrid application, this can be found under %localappdata%\Packages\<Your package folder>.  There will be 2 UDB files.  Copy them both to the same location as the iLoData.exe.  For example – ProductsOfflineStore.udb, ProductsOfflineStore.rq.udb
  • Run iLoData.exe with the following command to open the Offline Store.  For a complete list of arguments that can be passed, type in ilodata.exe /?

 

 

ilodata.exe service_root=com.sap.batch store_name=ProductsOfflineStore  appcid=a6de15ce-ba6a-41dd-90a2-2603573589f0

  • Run any OData commands to read the contents of the Offline Store.  For example

 

get /Products

get /Products/$count

get /Categories

get /Categories/$count

get /Categories(5)/Products


 

 

I have attached the index.html file for the hybrid application.  Please refer to the blog on how to set up SAP Web IDE application to run on Windows 10.  In addition, please refer to the blog on getting started with Kapsel. 

Further tweaking of JetBrains WebStorm for UI5 development

$
0
0

While self-studying UI5 development I tried both Eclipse and SAP Web IDE and I must admit neither worked for me as I expected. Not that I would list exact points of each I was completely dissatisfied with; just an overall - probably subconscious - perception. So from time to time I read a review or two of one or another Web development tool. After reading a great post Configuring JetBrains WebStorm for UI5 development of Robin van het Hof I decided to give it a try. And so far I must say it hit the spot.

 

Robin states in his blog that you have to retrieve two XSD files (sap.m.xsd and sap.ui.core.xsd) from Eclipse UI5 tools installation as they are not present in OpenUI5 SDK. And I did as he told. And then I discovered that actually both files are provided in OpenUI5 SDK archive. They are located in downloads\schemas folder (at least I see them in 1.34.8 version of the SDK). So, if you decided to start with WebStorm from the beginning you don't need to install Eclipse and its tools for SAPUI5.

2016-03-06_20-58-16.png

It turns out however that not everything is flawless. When implementing some tutorials from OpenUI5 guide in WebStorm you can notice that XML view files sometimes show red marks or report errors which should not be present especially when you copy and paste file contents from the tutorial.


For example, WebStorm reports an error when you mention namespace sap.ui.core.mvc in XML view file. Then you can see red marks under class attribute when implementing exercise Margins and Paddings. The same thing occurs with FragmentDefinition tag when doing tutorial step Dialogs and Fragments. Yes, the code works, but these flaws deprive you of a convenient and helpful code completion feature when designing XML views. Not to tell that superfluous error marks look annoying.


Google only helped to locate the problem and it turned out that WebStorm just cannot find sufficient validation rules in those two XSD files. Actually XSD file contains an XML schema; that is a formal description of a particular XML file format: a set of allowed tags, its attributes, attribute values, etc. Apparently each XSD file is a kind of XML. More details on XSD you can find here.


In our case two XSD files provided with OpenUI5 SDK just tell the WebStorm how to validate XML view files. Unfortunately Google did not helped much in the problem solution and so I decided to dive into XSD and fix it myself.

 

How to fix the sap.ui.core.mvc namespace

 

After configuring WebStorm as described in Robin's post I started implementing tutorials; and when entering XML view I noticed that namespace sap.ui.core.mvc is marked with red. No auto-completion available for View attributes (I wanted to enter controllerName value).

According to API reference a number of View types are present in the name space sap.ui.core.mvc:

  • HTMLView - A view defined/constructed by declarative HTML.
  • JSONView - A View defined using JSON.
  • JSView - A View defined/constructed by JavaScript code.
  • TemplateView - A view defined in a template.
  • View - A base class for Views.
  • XMLView - A View defined using (P)XML and HTML markup.

However there is no specific XSD file and all the views are present in sap.ui.core.xsd file. As we can see in sap.ui.core.xsd each of elements corresponding to views reference other Complex types in sap.ui.core.xsd. As in the example below the element JSView references the complex type n0:_JSViewType. And also we can see that the whole element description is quite short: just a reference to the complex type and annotation.

2016-03-07_12-33-20.png

So the plan would be as follows:

  1. Create a separate file for sap.ui.core.mvc
  2. Make a reference to the sap.ui.core XSD file
  3. Copy the necessary views declaration

The resulting file looks as below (the full file is attached):

2016-03-07_12-50-16.png

Note that we have a namespace declaration in the header: xmlns:n0="sap.ui.core". And then we have an import statement to make the parser aware where to find declarations from sap.ui.core name space.


Missing attributes

 

It appears that original XSD file for sap.ui.core name space does not contain some view attributes, hence WebStorm can not provide a correct auto-completion options when editing XML views. I noticed at least two attributes: controllerName and class.

 

The controllerName attribute belongs to View and its descendants and all original attributes of base element for views are linked to the _ViewType complex type in  sap.ui.core.xsd file. I added controllerName to the _ViewType complex type:

 

2016-03-07_16-11-08.png

 

The class attribute (which represents a combination of CSS classes - margin, colors, etc) is a part of Control and its descendants. So the right place for it is the complex type _ControlType:

 

2016-03-07_16-13-07.png

To make things more comfortable I also made a specific type for the class attribute. Now WebStorm suggest a list of all margin classes referenced in SAP documentation. However there is a drawback: The type allows only a single value while in reality the attribute accepts a sequence of class names separated by space. And currently WebStorm marks such values with red. Probably some XSD experts could come up with an alternative solution.

 

FragmentDefinition

 

WebStorm also marks tag FragmentDefinition with red and apparently there is no such element in any of the original XSD files provided. This tag represents a generic place holder for any type of a Fragment. And the particular type of fragment you select in the code of the corresponding controller (at least so I understand ). So it appears that we should add an element FragmentDefinition to the XML schema (our XSD file) which should not extend any other type; and at the same time it should allow the same set of sub-tags as a View. The following definition does the trick:


2016-03-07_16-27-24.png

 

 

Bottom line


Tweaking of XSD files is not so scary as it looked at the start. WebStorm now provides the correct auto-completion list. It reports errors with a multi value class attribute but for now I can live with it. I attached both tweaked files to the post. Just note that you should better change their extension to .xsd as SCN does not allow attaching of XSD files.

Hybrid app development & debugging with Netbeans, OpenUI5 and Chrome

$
0
0

Recently i read the interesting blog of  Florian Pfeffer about developing an hybrid application with the Thym plugin for Eclipse. That plugin is very helpful and as a result i got interested in IDE for developing hybrid applications and i discovered that, starting from 8.x releases, Netbeans IDE added a specific project type for Cordova applications. I tried it and in general i felt more comfortable than with Thym, so i'll show you how to get started developing and debugging a simple hybrid application using Netbeans and the geolocation plugin of Apache Cordova.

 

Prerequisites are installing for your platform:

 

 

and obviously the Netbeans IDE; i suggest also to install Git in order to have a version control system; i carried out the whole job on windows 10 with latest version of listed software.

 

To start building my hybrid application i simply followed the "Creating a Cordova Application" paragraph of the Getting started with Cordova applications in the Netbeans online knoledge base. With latest Netbeans release you'll probably see a "Tools" step instead of the the "JavaScript Files" step shown but doesn't matter, we will add later OpenUI5 libraries to our project. Leave everything as default and proceed. The IDE generates for you the "Hello World" skeleton code of the application. Having a quick look at the code of the index.html file generated under the site root of your project you can see that the body includes two javascript files: cordova.js and index.js. Do not worry if you don't see the cordova.js file under your folder! It will be automatically generated depending on selected cordova plugins when the application will be built. Now let's look at the index.js file under the js folder. Here your application will be initialized binding events; the generated code adds a listener for the deviceready event. When device is ready the code under receivedEvent method will be executed. You can test (and also debug using Chrome browser as will be explained later) your application on an emulator or directly on a device. My suggestion is to test directly on a device just because emulators used to run very slowly. At this moment the application simply shows a device ready logo (Fig.1). Right clicking on your project, under properties, it is possible to handle needed plugins as shown in Fig. 2.

 

Fig. 1Fig. 2

 

It's now time to add OpenUI5 runtime to the application. Download the latest OpenUI5 runtime from the above link, unzip and copy the resources folder under your www project folder; for my application i kept only minified javascript files and purged the non-minified debug files (-dbg.js). Your application is now ready to be modified in order to load the OpenUI5 core. Since i decided also to use geolocation Apache Cordova plugin to show a map i needed Google Maps Javascript API, so i added these two script tag to load OpenUI5 runtime and Maps API:

 

<script id="sap-ui-bootstrap" src="openui5/resources/sap-ui-core.js"                        data-sap-ui-libs="sap.m" data-sap-ui-theme="sap_bluecrystal"></script><script src="https://maps.googleapis.com/maps/api/js"></script>

 

To avoid any cross domain, unsafe styles ecc. issues and go straight to the point i also relaxed the specified content security policies; obviously in a real business application you can't leave everithing as unsafe.

 

<meta http-equiv="Content-Security-Policy"           content="default-src * 'unsafe-inline' 'unsafe-eval'           script-srcdata: gap: https://ssl.gstatic.com 'unsafe-eval';           style-src * 'unsafe-inline' 'unsafe-eval'; media-src *">


I modified the body to sapUiBody and added the container div tag for the sap.m.App. I also adapted to my needs the index.css file on css folder, especially to show the map: div#mapdiv {width:100%;height:100%;}. The OpenUI5 application i developed is very simple: there are 2 pages, the first one showing and updating your current location with an accuracy circle and the second one showing gps details. To fully achieve the result mainly i used following documentation:

 

 

In that basic application i generated views and controls with javascript and i didn't take into account developing guidelines, coding and performance issue ecc. As i said i wanted to go straight to the point. Before starting to develop a real business application from scratch i suggest you to take a tour of the developer guide on OpenUI5 official documentation. I won't show more code snippets: at bottom there's a link to my git repository on githubso that you can check it; main files are index.html, index.js and index.css. Last step: what about debugging? Debugging the application is very easy using Chrome browser (remember to enable USB devices on your phone); simply go to address chrome://inspect and under devices you'll find your phone and your running hybrid application. From there you can debug your code as if it was a usual web application (Fig. 3).

 

Fig. 3

 

Below two screenshots of the app running on my HTC One X.

 

Fig. 4Fig. 5

 

Lastly you can have a look at my code at github here. As you can see the application is very basic; i just wanted to show another option (using Netbeans instead of Eclipse with Thym plugin) to develop hybrid applications breaking free from CLI and accessing at least a native device API's through Cordova.


sap.m.SearchField.ShowRefreshButton property

$
0
0

Guru's,

 

we are @ SAPUI5 (1.28.29) SAP_UI 7.40 SP14 and running a SplitApp.

 

On OData Model does the "ShowRefreshButton" Property suppose to work? I don't see it doing what it's meant to.

 

View:

 

<subHeader id="masterSubHeader">

<Bar id="searchBar">

<contentMiddle>

 

<SearchField id="searchField" liveChange="onSearch" selectOnFocus="true" showRefreshButton="{device>/isNoTouch}" tooltip="{i18n>masterSearchTooltip}"

width="100%"></SearchField>

</contentMiddle>

</Bar>

</subHeader>

 

 

anything other than "device" or "True" will not work as it disables the property. Any ideas why it's behaving this way?

Project HomeControl - Smart meter / IOT / UI5 - Introduction

$
0
0

The European Union has decided that every house in Europe must be equipped with a Smart Meter. Here in The Netherlands the electricity company are replacing the old ones house by house, so it will take some time to replace them all, but that will be done before 2020.

 

It is possible to speed up the process by requesting a smart meter at some cost. Since I have an electric car, I thought I needed the smart meter for it, since the charging station can detect power usage of other equipment at home. I am charging the car at night, so no real issues fortunately. But the smart meter was ordered beforehand, so let's make use of it

 

Here is what I am going to do:

1) Connect the Smart meter via a P1 port to Arduino Uno (one of the many ways to get telegram messages from the Smart Meter);

2) Create a database (mySQL or MongoDB) and write a script for the Arduino to push every xx seconds a telegram message into the database located at my NAS;

3) Develop a service to request information from the database (NodeJS or php);

4) Develop a ui5 application to retrieve the information from the service and display it.

 

2016-03-10 11_23_03-homecontrol.pptx - Weergave voor PowerPoint-presentator.png

 

Waiting for the hardware to arrive

 

 

Noël Hendrikx

Running SAP Web IDE applications using HAT in Windows

$
0
0

Last month, I wrote a blog on how to run SAP Web IDE projects in Windows platform.  At that moment, Hybrid Application Toolkit (hereinafter, referred to as ‘HAT’) only supported Android and iOS.  Couple of weeks ago, I got an internal email mentioning preliminary support for Windows using HAT.  So here I am – writing another blog on how to run SAP Web IDE projects in Windows platform using HAT.  You will be amazed at how simple the entire process is. 

 

Download HAT installation files

HAT installation files can be found in this location.   https://store.sap.com/sap/cp/ui/resources/store/html/SolutionDetails.html?pid=0000013586&catID=&pcntry=US&sap-language=EN&_cp_id=id-1457454501039-0.  The current version of HAT is 1.12.5 and it supports Windows.  It is still in beta though.  I am sure it will be in release mode shortly.  There are no companion app for Windows yet.  So when changes are made to the project, the entire project is recompiled on the local machine.  I have tried running it on my Windows 10 laptop and it seems pretty fast.

 

Installing pre-requisites

          WebIDE1.png

 

  • Choose the Custom option. Select HTML/JavaScript (Apache Cordova) under Cross Platform Mobile Development

           WebIDE2.png

 

 

Installing HAT

Microsoft Visual Studio 2015 Community Edition with support for Cross Platform Mobile Development installs almost all of the pre-requisites required by HAT.  There are some environment variables that need to be set. But other than that, you are ready to install HAT on your local machine.

          WebIDE17.png

  • Select Windows (beta) and click Check All to test if the system is set up correctly.  Note that you might have to set up some of the environment variables.

           WebIDE18.png

  • Once all the checks are complete, HAT is installed on the local machine

          WebIDE19.png

  • There is no support for Companion App on Windows yet. So you can skip the Build Hybrid Companion App and exit out of the installation process.

 

 

Running SAP Web IDE application on Windows platform

  • Execute run.cmd from the HAT installation folder. You will be prompted for the HAT Connector certificate password.

           WebIDE20.png

 

  • From SAP Web IDE, select Tools -> Preferences. Click on Tools -> Preferences. Select Hybrid Application Toolkit in the left pane.  Click on Test Connection.  Make sure that HAT in your local system is able to connect to the SAP Web IDE system.

           WebIDE21.png

  • Create SAP UI5 Mobile application in SAP Web IDE using the templates
  • Under Device Configuration page, provide basic information for the application

           WebIDE22.png

  • Select Windows as your platform.  Also select the appropriate Kapsel plugins required for your application.  Right click the application and select run on Windows Local

           WebIDE23.png

 

Exploring application files

  • Selecting Windows Local will run the application on your Windows laptop.  Files are sent down to your laptop, the application is compiled and the application is run automatically. 

          WebIDE24.png

  • The files are stored under %userprofile%\SAPHybrid folder – if you are interested in exploring the file structure sent down to the laptop. 

          WebIDE25.png

  • Note that there is a copy of the SAP UI5 resources (sapui5-mobile.zip) that is sent down to your local machine.  The SAP UI5 resources are included in your application project.
  • Open your application project folder.  Browse to hybrid\platforms\windows folder.  The Visual Studio solution (CordovaApp.sln) for the application can be found here.  

 

As mentioned earlier, the support for running SAP Web IDE application using HAT in Windows is still in beta.  I will update this blog later once it is in release mode. 

UI5con recap

$
0
0

Logo_mit_Datum_small.png

 

The first ever conference, UI5con, specially focusing on sapui5 and openui5 was held this Friday in Frankfurt. It was jointly organized by UI5 SCN community, sitFRA organizers and SAPUI5 team from SAP. The conference focus was on technical aspects with lots of time also reserved for networking with fellow UI5 developers and enthusiasts.

 

UI5con had in total 80 attendees from all over Europe representing well over 10 different countries and it was a great opportunity for lots of people to meet face-to-face for the first time. The community interest into the conference well exceeded all expectations and it was sold-out in little over 40 minutes meaning that unfortunately lots of interested people couldn’t attend. Hopefully next time we will have much bigger venue and all interested people can secure a place.

IMG_20160311_093202.jpg

 

Many of the core SAPUI5 team members were also attending thus allowing community members to get some insight into how UI5 is developed and what is the future direction UI5 is directed to. I hope that the SAPUI5 team also got lots of useful feedback from community. At least they were really open to discuss all aspects of UI5 with the community. I still find it sometimes hard to believe, even after seeing it time after time again, that they have such a great culture of openness in that particular team inside SAP. Thanks and keep up the good work!

 

The UI5con day was fully packed with interesting sessions. All of the sessions had really interesting topics and it was really difficult to choose which ones to attend to as there were two simultaneous tracks going on. Fortunately all the sessions were recorded so look forward to watching them once they are released (maybe at the OpenUI5 Youtube channel)

 

After introduction from great hostess, Margot Wollny, the first session was held by Stefan Beck, Chief Product Owner of SAPUI5. He had an interesting talk about the history of SAPUI5 and OpenUI5, also with explanation for the origin of the phoenix in the UI5 logo. Stefan also explained the current areas of focus for UI5.

IMG_20160311_093555.jpg

IMG_20160311_094029.jpg

 

After Stefan’s session the conference sessions split into two tracks. From the two simultaneous sessions, I attended Nabi Zamani's session: “Hacking the Explored App by Adding Custom Code”. Nabi explained the usefulness of the Explored App from different type of users’ point-of-view. Then he went onto running the Explored App on his own computer and extended it with a new tutorial explaining how to embed PDFs into UI5. The session helped to understand how the Explored App works. On the other track, Benjamin Steinvorth gave a presentation with title: “Minimize time-to-market with UI5” sharing findings about implementing an UI5 prototype in two weeks.

IMG_20160311_102444.jpg

 

Next one up were HP Seitz and Sean Campbell. HP Seitz gave a session on Full-stack JavaScript with OpenUI5. Sean had bribed me to attend to his session with couple beers (Thanks Sean!), so I only heard the last few mins of HP’s session, but already from that it seemed to be a really interesting session. I look forward to watching the recording of that. Sean’s session was about Building C4C companion apps or about a simple HCP UI5 ticketing application backed with a C4C OData service. Interesting topic and session and I learned a lot from it not having been introduced myself to C4C before.

IMG_20160311_104512.jpg

 

After a little break these was yet again two very interesting sessions going at the same time. Andreas Kunz gave us a presentation about custom UI5 controls introducing how to roll-up your own and what to keep in mind while doing so. The session was a little extended version from the one Andreas and Denise Nepraunig presented at UI5 Codejam in the Netherlands last November. Anyhow, even after listening the NL one, I still learned so many things. On the other track, Leo van Hengel, gave a talk: “Building Custom Site Templates for the new SAP HANA Cloud Portal with SAPUI5”. I am looking forward to watching the replay of that session also.

IMG_20160311_113021.jpg

 

After a well-deserved lunch break (thanks organizers for providing that), it was time for some lightning talks. First Denise showed us some Unexpected SAPUI5 Apps about Chuck Norris jokes (can’t go wrong with those) and Star Wars. Great to see example apps with something so different. Actually the whole conference was about community and interesting cases and not some typical business stuff. After Denise, it was my time to show how you can use UI5 apps by voice controlling instead of using mouse and keyboard. “Next”! Then it was time for Andreas Frische to show how you can use Type Script with UI5. It’s great to see that you can really integrate UI5 with anything, be it in the tooling side or related to other Javascript libraries.

IMG_20160311_130204.jpg

 

After the first set of lightning talks, the conference switched back to two track setting. On track 1, Helmut Tammen, explained Building Custom Graphical Control Using SVG (see the map below) with additional Usage of OData Server for node.js (or “no data server”). Interesting session overall and I really appreciate his work on implementation of an OData server for Node.js. On track 2, Qun Li and Ian Taylor explained “Using SAP Fiori Reference App as a Basis for your UI5 App”. Reference Apps are something I’ve gave a look into but still haven’t get used to taking advantage of enough.

IMG_20160311_141207.jpg

 

Switching tracks again, I listened to Tomasz Mackowski introducing Continuous integration in UI5 projects. CI is really the one aspect that we as a community must really focus into in order to become more mature and professional. But luckily it’s not something you either do the whole way or do not do at all. Tomasz explained many different potential starting, or continuing, points that we all can look into. The talk also inspired a vivid discussion among the attendees which really explains how everyone could share their thoughts at UI5con. During Tomasz’s session, Mark Schmale talked about “Combining UI5 and SAP LO VC for fun and Profit”. Look into the session recordings regarding that one.

IMG_20160311_144809.jpg

 

After a break, it was again time for some lightning talks. Dynamic duo: Wouter Lemaire and Jeremy Coppey presented how you can have it object oriented way all the way from ABAP to Fiori and back. Matthias Bollen and Tobias Trapp continued on “Analysis Path Framework – A Hidden Gem for Creating UI5”. I have to acknowledge that already at that point I was so overwhelmed from all the great sessions and can’t remember much from that lightning talk and it really had nothing to do with the talk itself. But that’s another good reason to watch the replay.

IMG_20160311_154210.jpg

 

Next one was Maximilian Lenkeit giving longer presentation titled “Building Custom Controls to Visualize Data”. The session content was so packed and Maximilian had so many great things to show that he probably could have extended it to a half-day session quite easily. Maximilian also had the most awesome demo of the day with IoT sensor in a container that connected to real-time Fiori Launchpad apps visualizing sensor data in 3D.

 

See video example by Utsav Chobe

 

IMG_20160311_160525.jpg

IMG_20160311_160753.jpg

 

 

At the same time with Maximilian in the other room, Nathan Adams gave a presentation from a different perspective titled: “Developers are not designers”. After the session I talked with Nathan about design and usability from both user’s and developer’s point-of-view so long that we both missed the following sessions altogether. First of those sessions was presented Denny Schreber and Katrin Grohme and the topic was “Lessons Learned from SAPUI5”. The second was Volker Buzek“Inside a Container Persistence and UI5”. Both sound interesting so I recommend watching the replays from those. I will definitely watch them myself.

 

Then finally after a looong but wonderful day the last presentation was about OpenUI5 Spirit by Michael Graf from the UI5 team. It was great to see how SAP manages OpenUI5/SAPUI5 and how open sourcing the core framework has affected the using of tooling and development processes in the team.

IMG_20160311_174428.jpg

 

After that, the organizing team wrapped up the conference and most of the attendees continued to the well deserved evening event for networking and having fun.

 

Thanks for all the organizers, speakers and attendees for such a wonderful day.


See you in the next UI5con!

How to Use Controls from a Newer UI5 Version in Your UI5 App Without Upgrading - But in an upgrade friendly way

$
0
0

Before I start, this is my first blog so sorry for the poor formatting.


Summary and Background: At a client we were implementing a customized version of the My Timesheets v2. We did not have the latest version of the UI5 libraries and were not able to upgrade them. The standard app uses a DateTimeInput control which renders as a picker on both Desktop and mobile devices. This is a pretty poor UX on desktop since it is much easier to type than try and use the scroll wheel to go through numbers. So the new requirement was to allow text input on the desktop and picker use on the mobile. Very quickly we saw that there was a control for this, TimePicker, and in fact that the control used in the standard app is deprecated. So we made this change in our local apps (running in Eclipse/Tomcat environment) and it worked fine! However as soon we uploaded the app to the Gateway server it would not render. We realized our mistake was that our Eclipse environment had a new library version (which had the Timepicker control) and the gateway server had an older version without the control. We did not want to write a control ourselves, so we tried to extract the control for the library in Eclipse, and include it in our custom app. Obviously we succeeded or this post would just say 'you can't do it sorry folks.' Doing this method has a few benefits over writing a custom control 1) Its less work (and lets be honest that's what all developers want) 2) When the library version is finally upgraded it is a very simple process to have your app use the standard code again and remove these smalls customizations, with no impact to UI/UX for the end users (assuming you change from a custom control to a standard one upon upgrade)

Note: This post does assume use of a custom theme in order to work some CSS voodoo, you should be able to just include the custom CSS in your app but I have not done that before I just use theme designer so if you try this yourself and don't use theme designer let me know how you did it.


Procedure:

  1. First, we need actual JS files that allow this control to function. To extract them, we added the control to our view in our Eclipse project. In this example all we did was replace the XML which before said ‘DateTimePicker’ with ‘TimePicker’ and modified the attributes slightly so the Timepicker rendered how we wanted (it took 1 new formatting parameter than the old control). We then save our project (which should be deployed on a tomcat server or similar).
  2. We open Google Chrome, and open the developer tools window, then access our app. Navigate to the screen which the new control will be rendered on. Access the network tab in dev tools, and you will see the individual .js files for all the controls being downloaded. You will see one with the same name as your control, in this case TimePicker.js Click in the file to open it in a preview window. Use ‘Pretty Print’ to open a TimePicker.js:formatted file. Copy the code and paste it into your own TimePicker.js
  3. The code should be in one line (if you did not use pretty print as recommended above), you will need to space it out to see from the ‘define’ statements what other js files are using by the main control js file. In this case we can see that MaskInput, MaskInputRule, and TimePickerSliders are needed, as well as some base files which should still be in our older UI5 Lib version. So we need to go back to the network tab and copy those files out and create our own local version of them. If you examine their files you will see some more that are needed. You can also just look at the network tab and see that after TimePicker is loaded there are about 8 other .js files that are loaded. We could determine this by deploying our app with these custom files to our ABAP server and checking the console for errors as each time the app would try and load a new .js file that isn’t there, but we can generally tell what .js files are needed on the first try and if we miss one, simply add it using the steps detailed below. All in all we end up needing the following files: MaskInput, MaskInputRule, TimePicker, TimePickerRenderer, TimePickerSlider, TimePickerSliderRenderer, TimePickerSliders, TimePickerSlidersRenderer. TimePickerRender is the only one not explicitly ‘defined’ in one of the other files, but we see it is downloaded in the network tab, or we could leave it out and try to deploy the app without out to ABAP server and quickly see we need to have it. Regardless we now have local copies of these 8 files (ideally pretty printed to readable format).
  4. Now we need to add these files to our project. We created a new directory called ‘control’ and add these .js files to them.
  5. Now we need to modify the xml view that we added the control to previously. The current setup will look in the default XML namespace which is sap.m library of UI5, we need it to point to our control folder so we add a new namespace to the xml and modify the XML to use it for the TimePicker
    1. Namespace in our example: xmlns:hcm.mytimesheet.Z_HCM_TSH_MAN.control="hcm.mytimesheet.Z_HCM_TSH_MAN.control
    2. We delete the standard code:<DateTimeInput id="startTime" change="validate" type="Time" value="{entry>/startTime valueFormat="HHmmss" placeholder="{i18n>FROM}"> </DateTimeInput><DateTimeInput id="endTime" change="validate" type="Time" value="{entry>/endTime}" valueFormat="HHmmss" placeholder="{i18n>TO}"> </DateTimeInput>
    3. We add this custom code:<hcm.mytimesheet.Z_HCM_TSH_MAN.control:TimePicker id="startTime" change="validate" type="Time" value="{entry>/startTime}" displayFormat="HH:mm" valueFormat="HHmmss" placeholder="{i18n>FROM}"> </hcm.mytimesheet.Z_HCM_TSH_MAN.control:TimePicker><hcm.mytimesheet.Z_HCM_TSH_MAN.control:TimePicker id="endTime" change="validate" type="Time" value="{entry>/endTime}" displayFormat="HH:mm" valueFormat="HHmmss" placeholder="{i18n>TO}"> </hcm.mytimesheet.Z_HCM_TSH_MAN.control:TimePicker>
  6. So now our app will look in our added folder for the TimePicker file! But, due to the structure of the ‘define’ statements in the TimePicker.js (and other files) it will still fail. We need to make two types of modifications. There are files that were located in sap.m in the new library version that are now located in this directory we need to make sure their directory path is ‘./’ There are files that were located in the same directory as TimePicker.js in the newer library version, but we need to continue to fetch from sap.m so we need to change the path to ‘sap/m/’ whereas before they were pointing to current directory which would have been sap/m/ but is now our app’s control folder. So for all 8 files make the below changes:
    1. Is the .js file located in the control directory? Make sure file path is ‘./<X>’
    2. Is the .js file located in the standard library? Make sure the file path is ‘sap/m/<X>
    3. Example from TimePicker.js -  see all custom files are ./ all standards are sap/m : sap.ui.define([ 'jquery.sap.global', 'sap/m/InputBase', ./MaskInput', ./MaskInputRule', 'sap/m/ResponsivePopover', 'sap/ui/core/EnabledPropagator',  'sap/ui/core/IconPool', 'sap/ui/model/type/Time','./TimePickerSliders' ],
  7. In added .js files make sure any ‘require’ statements for files that exist in the added ‘control’ directory have the correct namespace this is: 'hcm.mytimesheet.Z_HCM_TSH_MAN.control.’ This only occurred in the TimePicker.js file, changes below:
    1. q.sap.require('hcm.mytimesheet.Z_HCM_TSH_MAN.control.MaskInputRule');

    2. q.sap.require('hcm.mytimesheet.Z_HCM_TSH_MAN.control.MaskInput');
  8. The TimePickerRenderer is not explicitly required and set as the TimePicker’s Renderer in the TimePicker.js code (as mentioned in step 3), so when the TimePicker is rendered in the browser one of the core UI5 functions generates a require statement based on the TimePicker’s class. The standard class is sap.m.TimePicker, with this the core function generates a require statement for sap.m.TimePickerRenderer which fails due to the renderer being in the custom control folder of the app, not the sap.m lib. So we need to change the class name to be in the namespace of the custom folder. Then the code will auto generate a require statement with the correct path.This took far longer than I care to admit to figure out.
    1. Change this line: var d = M.extend('sap.m.TimePicker', {
    2.   to: var d = M.extend('hcm.mytimesheet.Z_HCM_TSH_MAN.control.TimePicker',{
  9. At this point the view with the TimePicker will load without error, however the .css needed for the control to function properly has not been added to the project yet. The text input works but if you open the picker it is shown as plain text and you cannot select anything. We extract this .css (all classes with sapMTimePicker) and then we add this custom CSS to a custom theme. Check the prerequisite section on how to add a custom theme to your app if you did not already
  10. First we extract the needed css from the standard library
    1. Run the app again on your local server that has the newer library version
    2. Access (in chrome) the view that contains the TimePicker, open the picker and right click and select inspect this will open the html for it in the dev tools window
    3. In the chrome dev tools window click an html line, on the right hand side you can view the css classes related to that html element and there will be a link to library.css where the classes for these elements are. Click that link to view the .css file in Chrome Dev Tools Sources tab and see the file with the classes we need.
    4. Use the chrome pretty print button (‘{}’ in the bottom left of dev tools Sources tab) to view the code in a readable format in a new tab. Side Note: you can use pretty print on single line js files like sap core libs to set breakpoints that can really help debug, this is how I was able to find the issue with TimePickerRenderer having its require statement auto generated
    5. Copy and paste the file into a code editor like NotePad++, extract the classes that are related to sapMTimePicker
      1. I just ctrl+F’d for anything with that in it, which I saw was the class in the html in the screen shot above
    6. Access the NWG server and launch the theme designer
    7. Access your custom theme and open for editing
    8. Click the custom css tab and paste in the classes just extracted
    9. Save and build the theme
  11. Now the control will render when the app is launched with the custom theme parameter in the URL. The only issue is text like ‘Ok,’ ‘Hours,’ etc. will not be displayed correctly. As there are .getText() call which reference entries in the sap.m resource bundle which do not exist in the lower version of the library being used. So the .getText calls need to be replaced with correct strings. Alternatively you can modify the new .js files to point to a custom resource bundle.
    1. TimePicker.js
      1. Remove/Comment:
        1. //O = r.getText('TIMEPICKER_SET');
        2. //C = r.getText('TIMEPICKER_CANCEL');
      2. Add
        1. O = "OK";
        2. C = "Cancel";
    2. TimePickerRenderer.js
      1. Remove/Comment
        1. //t = o.getText('TIMEPICKER_SCREENREADER_TAG');
      2. Add
        1. t = "Time Picker";
    3. TimePickerSliders.js
      1. Remove/Comment
        1. //var r = sap.ui.getCore().getLibraryResourceBundle(

          //'sap.m'), l = r.getText('TIMEPICKER_LBL_HOURS'), L = r

          //        .getText('TIMEPICKER_LBL_MINUTES'), s = r

          //        .getText('TIMEPICKER_LBL_SECONDS'), b = r

          //        .getText('TIMEPICKER_LBL_AMPM');
      2. Add
        1. var r = sap.ui.getCore().getLibraryResourceBundle('sap.m'),

          l = "Hours",

          L = "Minutes",

          s = "Seconds",

          b = "AM/PM";
  12. The control should now render correctly in your app!

 

How to Undo These Changes When You Upgrade Your Library

  1. This is pretty easy, just remove the custom name space from the XML view, and make sure to change the actual part of the XML view that invokes the control to use the standard namespace.
  2. Remove the 'control' directory and all associated files inside
  3. Remove custom .css from the theme
  4. BAM your app is now just rendering the standard control again with no changes to the UI/UX!



This was a specific example but this idea should be applicable to any control you want to use.

 

If anyone else has accomplished something like this before in an easier way I'd love to hear!

Chrome Development Tool tips used in my daily work

$
0
0

I would like to use this blog to record the tips of using Chrome development tool in my daily UI5 application development life.

 

The version of my Chrome is: 49.0.2623.54 beta-m (64-bit).

 

1. Quickly navigate to the given line of code in source file

 

In Source tab, select the source file, for example "jquery.sap.act-dbg.js", press Ctrl+O, type ":<the line number which you want to navigate>", press enter key:

clipboard1.png

Destination reached:

clipboard2.png

2. Quickly find the source file you want

 

Click Sources->Sources, press Ctrl+O and type the file name character by character. Automatic completion is supported and thus very convenient to search.

clipboard3.png

3. Alt + Click to expand all children nodes in Elements tab

 

By default when you click the small triangle icon in Elements tab,

clipboard4.png

only its direct children node will be expanded:

clipboard5.png

Use Alt + Click to expand ALL its children.

 

4. Alt+Drag to select multiple lines

 

Suppose you only want to select the content after "||" in line 1476 ~ 1477. By default it is not possible.

clipboard6.png

You can first press Alt, and then perform your selection as usual ( by dragging mouse ).

It is then done:

clipboard7.png

5. Use $0 to get reference of currently selected html element in console tab

 

Suppose you use "Elements" tab to inspect the html tag of a given UI control instance:

clipboard8.png

You can simply type "$0" in console tag to get its reference:

clipboard9.png

And could directly modify its attribute in console and change will immediately take effect after enter key is pressed:

clipboard10.png

6. copy and values command in console tab

 

Still use the $0 in tip #5 for example. In console tab the command copy($0) will put all the source code of this html tag to the clipboard in your laptop,

clipboard11.png

so that you can just click Ctrl + C to get it in other place:

clipboard12.png

And command values will get all the attributes values of current object and display it as array:

clipboard13.png

For sure you can use both in chained style:

clipboard14.png

More tips to be added ...

Step by Step to create CDS view through SmartTemplate + WebIDE

$
0
0

1. Create CDS view based on sample database table spfli and scarr

 

Create two CDS views in ABAP development studio. The source code for both are listed below. You just need to copy them into studio and click activate button.

 

@AbapCatalog.sqlViewName: 'zjerrySQL0309'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'test 20160309'
@ObjectModel: {   createEnabled,    deleteEnabled,   updateEnabled
}
define view Zjerrytest20160309
as select from spfli association [0..1] to scarr as _scarr
on _scarr.carrid = spfli.carrid {       key spfli.carrid,       key _scarr.carrname,       key spfli.connid,       spfli.cityfrom,       spfli.cityto
}
@AbapCatalog.sqlViewName: 'z20160316'
@AbapCatalog.compiler.compareFilter: true
@AccessControl.authorizationCheck: #CHECK
@EndUserText.label: 'test odata publish '
@OData.publish: true
@ObjectModel: {   type: #CONSUMPTION,   compositionRoot,   semanticKey: ['Actor'],   createEnabled,    deleteEnabled,   updateEnabled
}
define view Zjerrytest20160316 as select from Zjerrytest20160309 {    @UI.lineItem : [{position:10}]    key Zjerrytest20160309.carrid as Jerryid,    @UI.lineItem : [{position:20}]    key Zjerrytest20160309.carrname as name,    @UI.lineItem : [{position:30}]    key Zjerrytest20160309.cityfrom as startLocation,    @UI.lineItem : [{position:40}]    key Zjerrytest20160309.cityto as target,    @UI.lineItem : [{position:50}]    key Zjerrytest20160309.connid
}

Once activated, there is a hint in studio to tell you the automatically published OData service name, and then tcode for service registration.

clipboard1.png

2. Use tcode /IWFND/MAINT_SERVICE to finish OData service registration

 

clipboard2.png

Specify System Alias = LOCAL and search using the CDS name you get from step1, select the search result and click "Add Selected Services":

clipboard3.png

Once added, click "SAP Gateway Client" to test whether the OData service works:

clipboard4.png

Make sure the metadata request returns 200 success code.

clipboard5.png

3. Create UI5 application using Wizard in WebIDE


Open WebIDE, File->New->Project from Template, choose Smart Template Application and next:

clipboard6.png

clipboard7.png

Select the destination for your backend where CDS view is created, and locate your OData service created just now:

clipboard8.png

The annotation file is automatically identified, just click Next button:

clipboard11.png

Choose OData Collection from drop down list and click Finish button:

clipboard12.png

Once created, the project looks like below. Choose Component.js and click Run button in WebIDE Toolbar:

clipboard13.png

From rendered application you could see the table is now filled with data fetched from CDS view:

clipboard14.png



How to add ODATA Service on SAP UI5 application available in Web IDE

$
0
0

Hi Everyone,

 

I want to discuss the way in which we can use ODATA service into SAPUI5 application available into the Web IDE.

 

Right now when we are creating SAPUI5 application from Web IDE it is not asking to attach ODATA service and hence we are not able to access the service, I am writing this blog as I saw some blog where this question was raised.

 

Solution : To add ODATA service you have to follow below steps.

 

1. Create your sap ui5 application like you are creating.

 

2. Now select the application and go to File -> New -> Odata Service

 

3. Now from here it will be same as we are doing for FIORI.

 

4. After you finish with adding of odata service in your application , check manifest.json file and you will be able to see your service now added.

 

5. Now you have to do same as you are doing in FIORI to access the service.

 

 

Thanks,

JP

How to Define OData $top-Parameter for an aggregation binding

$
0
0

Setup: A UI5 Application using a OData Model

Target: Limit the data that is fetched for an aggregation binding by specifing the $top parameter

Why?: This solution works with any aggregation binding. Not only when using a control based on the sap.m.ListBase, which provides properties for specifing the number of records that should be returned.

 

Solution: In the definition of the aggregation binding specify the parameter "length":

 

Example:

Length - Code Snippet.png

In this example a list of the first three business partners should be rendered. Therefor only the first 3 need to be loaded.

This will then result in the following OData Request:

 

    ../BusinessPartnerSet?$skip=0&$top=3


I could not found this feature in the documentation so thats why I'm sharing this with you.

Globalization(i18n)

$
0
0

Internationalization and localization

It is a way, how a computer software could be adapted to different languages. Internationalization(i18n) is actually the process of designing a software so that it can be adapted to different languages across the world, here 18 stands for number of alphabets between I & n.  Localization is the process of adapting internationalized software for a particular region or language by adding locale-specific components and translating text.

We use internationalization and localization in our Sapui5 application for replacing the hard coded text from the application. It is one of the best practices of SAP to use i18n for hard coded texts.  Generally we use Resource Model for defining, since it is one way binding (sap.ui.model.resource.ResourceModel)

The i18n model is set up in the Component's initialization section, or it could also be defined in the manifest.json file.

//set i18n model

var rootPath = jQuery.sap.getModulePath("sap.ui.demo.tdg");

 

Vari18nModel = newsap.ui.model.resource.ResourceModel({

          bundleUrl : "i18n/messageBundle.properties"});


          oView.setModel(i18nModel, "i18n");


Now create a folder named i18n in the project directory and maintain i18n files according to the languages.

 

The configuration specifies the relative location of the resource bundle. This is made absolute (in relation to our app's namespace) by use of the

jQuery.sap.getModulePathutility function, and then used to create the named model, before it is set on the component.

Now in the i18n.properties file, enter all the hard coded text that has been used in the application. And bind the data using the i18n model


Example

<Tableid="idOrderTable">

 

      <columns>

            <Columnwidth="8em">

                  <Texttext="{i18n>s3OrderColumnSales}"/>

            </Column>

            <Column>

                  <Texttext="{i18n>s3OrderColumnDelivery}"/>

            </Column>

            <Column>

                  <Texttext="{i18n>s3OrderColumnOrder}"/>

            </Column>

            <Column>

                  <Texttext="{i18n>s3OrderColumnRequested}"/>

            </Column>

            <Column>

                  <Texttext="{i18n>s3OderColumnAmount}"/>

            </Column>

      </columns>

</Table>

 

Here we have used a table and, the column text name is a hard coded value, hence we are using i18n model for the same.  Now we have to maintain the same fields in the i18n.properties file.

s3OrderColumnSales=SalesOrder

s3OrderColumnDelivery=DeliveryStatus

s3OrderColumnOrder=OrderDate

s3OrderColumnRequested=RequestedDate

s3OderColumnAmount=OrderAmount

Hence this is done, now to serve the real purpose of i18n file, another file will be created in the i18n folder for the german language. Name it as i18n_DE.properties

 

Now, maintain the same field names in this particular file.

s3OrderColumnSales=Kundenauftrag

s3OrderColumnDelivery=Lieferstatus

s3OrderColumnOrder=Auftragsdatum

s3OrderColumnRequested=Wunschtermin

s3OderColumnAmount=Bestellbetrag

Now to see the output, in german language, just add DE instead of EN in the application url. Add ?sap-ui-language=DE after the url.

Suppose the default url is:

http://localhost:42067/demo_i18n/index.html just add ?sap-ui-language=DE.


Now the url would be :

http://localhost:42067/demo_i18n/index.html?sap-ui-language=DE


Output

Deploying UI5: Introduction

$
0
0

In Javascript development the code that you write is never quite the code that you want in production.

 

The code you want to write has jsDoc, meaningful and by extension long variable names and white space to make it a delight to read just to name a few.

 

The issue is that these things that make it easy for the code to be read and makes it larger and longer for a browser to download it, leading to slower code.

 

What we need to do is to have a build and deploy process, ideal one that integrates with our source control. Graham Robinson has explored some of these ideas in his blog, SAPUI5-Deployer Project. I had a couple of key conversations with Graham as he was putting this together.

 

Recently when I arrived on another client I realised that our needs were similar but different.

 

  • We still need to get the code from the developer machine to gateway system efficiently.
  • We need to minify the code to reduce load times
  • We would like to have -dbg versions of the code so that we can toggle the debug mode in QA or Production systems.
  • We would like to add a component-preload.js file as described by Mattius in Optimizing UI5 Apps
  • I would like to make the command line build process as simple as possible.

 

In our situation our source code control is inside the firewall all this process needs to happen inside the firewall also.

 

There is too much here to cover in one blog so I am going to make this a series of blogs so that you can easily digest this.

 

Before we get to the next piece of the puzzle, let me introduce Grunt.

 

Grunt is a task runner. There is nothing new in this make, maven and ant are all examples of great task runners and they are all great tools.

I settled on grunt as it was tools that the UI5 team had also chosen. If you  have a local clone of UI5, you will see how grunt is used to build UI5 itself.

 

The other great thing about Grunt that it is javascript based and runs on nodejs. All these skills are excellent to have as you develop as a UI5 developer.

 

In the next blog we will install node install grunt and get our first task running.

 

|-- Previous blog You are at the beginning!  Next blog: Solutions and Scenarios -->

WebIDE Ninja #1: Consume 3rd Party services with UI5

$
0
0

ninja-logo.png


This blog is the first one of a series of blog which we like to call “Becoming a Ninja Web IDE Developer”. This series will expose advanced topics in Web IDE beyond the standard Fiori development which you all mastered by now.

 

Prerequisites

 

  • SAP Web IDE instance - either trial or production (you can get one here: SAP HANA Cloud Platform )
  • Knowledge in UI5 development and data binding
  • Modern web browser (chrome/firefox etc.)
  • Have a quick look at the Open weather API - Weather API


Introduction

 

Most of the common apps that are implemented with Web IDE and UI5 are apps which consume oData services from SAP backend. Creating a UI5 app in Web IDE which consume oData is pretty straight forward using Web IDE rapid development tools you can generate an app which consume oData easily using template wizards, WYSIWYG, Extensibility and more.. but what if the API that you are trying to consume is not an oData API but JSON REST API? and what if in addition to consume oData you want also to consume other REST services which are available out there like: Facebook , twitter, google API's, weather and more. Most of the public API's which exist today expose their data in simple JSON format and not built on top of the oData protocol and currently you cannot use all the rapid capabilities of Web IDE for developing an app which consume such services.

 

In this blog post we will show how we can create a simple app which consume 3rd REST service with SAP WebIDE. we will also use as many as tools that we can that are part of Web IDE in order to reduce the development time to a minimum and will write my code according to the SAPUI5 and Fiori guidelines (data binding, xml views, component and more).

 

Let's get started!

 

Open Weather API

 

The 3rd party API that we will consume in this app will be the Open Weather API. We selected this API because it      is an open API which not require signup or login for test/demo purposes.

the specific URL that we will use in our app is described here: forecast16

 

The App

 

The app that we will create will be a simple app which will consume the open weather API and will show the forecast in London (can be changed) for the next 16 days.

The result of this blog post will be an app that will contain 2 UI elements:

  • Object Header - will show  the country and the city SAPUI5 Explored
  • Table - will show the forecast of the next 16 days (date,average degrees,units and humidity)  SAPUI5 Explored

 

The app UI will be like the following:

 

1 - final app.png

As you can see from the image above the app is simple because the idea of this blog post is to show all the relevant steps that are required in order to develop an app which consume 3rd party services in the Right Way!

 

 

1 - Generate an empty app

 

  • Open your Web IDE instance
  • Click on File --> New --> Project From Template
  • In the dialog select SAP Fiori Application in the first combobox and then select the SAPUI5 Application tile
    2-sapui5 dialog.png
  • Click Next and fill in the following details in the next window
    • Project Name: OpenWeatherSample
    • Namespace: com.demo
    • Leave the set this project hybrid mobile application unchecked

      3 - dialog sec step.png

  • Click Next and on the next step fill in the following details
    • View Type: XML
    • View Name: Main

      4 - third step.png
    • Click Finish --> a new project will be generated into your Workspace.
    • The project structure should look like the following:

      5 - project structure.png

 

 

2 - Create destination in HCP cockpit

 

Now we are ready to create a new destination in HCP cockpit that will point to the open weather API.

creating of new destination is required in order to avoid cross origin (that the host where the apps run on try to access a different host in our case is the open weather API host). More details about CORS can be found here: HTTP access control (CORS) - HTTP | MDN

 

Please do the following in order to create new destination:

 

  • In Web IDE go to Tools --> SAP Hana Cloud Platform Cockpit to open the HCP cockpit

    6 - go to HCP cockpit.png
  • In the HCP cockpit select Destinations (from the left menu)
  • Click on New Destination button the create a new destination and fill in the following details:
    • Name: OpenWeather
    • Type: HTTP
    • Description: Open Weather API
    • URL: http://api.openweathermap.org
    • Proxy Type: Internet
    • Authentication: No Authentication
    • Additional Properties:
      • WebIDEEnabled: true
      • WebIDESystem: API
  • Click Save to create the new Destination .

    7 - new destination.png
  • Or you can download the attached destination that we uploaded and import it to your HCP cockpit

 

 

3 - Add the new destination to neo-app.json

 

In order to use this destination in our app we will need to add it to the neo-app.json file. The neo-app.json is the configuration file of the HCP front-end server. This file contains all the services/destinations that are required in order to app to run on the HCP server.

 

In order to add our new destinations please do the following:

 

  • Go to Web IDE and expand the OpenWeatherSample app (the one that we generated in the first step)
  • Double click on the neo-app.json to edit it
  • Under the routes array add a new object with the following details:
{      "path": "/OpenWeather",      "target": {        "type": "destination",        "name": "OpenWeather",        "entryPath": "/"      },      "description": "Open weather API"
}
  • Now, in order to consume the Open Weather API the only thing that we will need to do in code is the call to "/OpenWeather" behind the scenes HCP front-server will search for a destination with name "OpenWeather" and will redirect us to the URL that we specified in the destination
  • If you are having troubles with modify the neo-app.json file you can just download the file that we attached and replace it with the one that you have in your workspace. (please make sure that you don't change the name of this file)

 

4 - Design the app UI

 

In this section we will create the UI for our app.

Like we mentioned above for this simple app we will use only 2 UI elements an ObjectHeader and a Table

we also mentioned that we will use as many as tools as possible in order to reduce the development time and complexity, specifically for designing the UI we will use the Layout Editor (WYSIWYG) which is a tool that allow developer to create UI by dragging&dropping UI5 controls into a canvas.

 

  • Expand the View folder and select the Main.view.js file
  • Right click on the file and select Open With --> Layout Editor
    8 - open layout editor.png
  • Web IDE layout editor will be opened with an empty view
  • Now we have 2 options to add UI elements into our canvas:
    • By dragging & dropping them from the left side (under controls tab) into the right side (the canvas) - This is the what we will do
    • By using the outline there you can add UI elements by right click on one of the controls and select Add in order to add elements into it
  • Please do the following in order to add the UI elements into the view
    • Make sure the Controls tab (appear on the left side) is selected
      9 - controls tab.png
    • Using the search box search for ObjectHeader control and select it
    • Drag the ObjectHeader control from the left side into the right side and make sure it is located on the top of the page
      10 - drag objectheader.png
    • Again, using the search box this time search for Table and select it
    • Drag and drop the Table control and make sure it is located under the ObjectHeader
      11 - drag and drop table.png
  • Next we need to change the UI elements properties according to our needs. Because the layout editor currently supports only oData model binding we will need to do some manual changes in both the XML code editor and the layout editor.
  • Please do the following for the changes that we need to make in the Layout Editor
    • From the right side canvas select the ObjectHeader control
    • After the control is selected you will be able to see and change the control properties. The control properties are located on the right side of the canvas
    • Please change the following properties
      • Title: {/country}
      • Intro: {/city}
      • Number: Leave it empty
      • Number Unit: Leave it empty

                12 - objectheader props.png

  • Now we need also to change the Table control properties but this time we will do it in the XML code editor (and not in the layout editor)
    • From your workspace select the Main.view.xml file and double click on it to open in with the XML code editor
    • In the code editor search for the <Table tag and add the following attributes:
      • columns="{/cols}"
      • items="{/items}"
      • Remove the attribute of noDataText
    • After making the changes to the Table tag it should look like the following:
      <Table items="{/items}" columns="{/cols}"  id="__table0">
    • Under the <items> tag please make sure that you have only one <ColumnListItem> which looks like the following:
      13 - columnlistitem.png

      Notice that the {date} , {temp} ... are placeholders for the model data binding. We need only one ColumnListItem under the <items> because this ColumnListItem act as the Template so each row of the table will have 4 columns (date,temp,units and humidity)

    • Now we need also to create the template of the table columns. Like we did for the <items> tag we need to do for the <Columns> tag but this time we will use <Column> tag under the <Columns> and not <ColumnListItem>
    • Under <Columns> please make sure you have only one <Column> which looks like the following:
      14 - column.png
    • After all the changes your Main.view.js file should look like the following:

      15 - main view.png

 

 

5 - Writing the business logic

 

Setting up the data model

 

Before we start writing the code inside the app controller we need to create our model. Our model will contain all the data that should be presented in the UI that we just build.

Our data model should contain the following information:

  • Country
  • City
  • List of days so each day in the list should have
    • Date
    • Average temperature
    • Units
    • Humidity

In addition the data model should contain the columns of the table.

 

In order to create our data model please do the following:

  • Select the file models.js which located under the model folder
  • Create a new function with name createAPIModel
  • Inside the function body we need to create our model. Because we consume 3rd party JSON service we must use JSONMODEL (and not ODATAMODEL) so our function body must contain the following lines of code:

    16 - api model.png

  • As you can see from the screenshot above our data model contains the city, country, list of columns and list of items (currently empty)
  • Next we need  to set this model as our global model. To set our model as the global model please do the following:
    • Select the Component.js file and open it for edit
    • Add the following line of the to the bottom of the init function

      this.setModel(models.createAPIModel());
  • Last thing on the UI that we need to do is to change the title of the page in order to change the title please do the following:
    • Expand  the i18n folder
    • Select the i18n.properties file and open it for edit
    • change the following:
      • appTitle = Open weather API
      • title = Open Weather
    • after we made the changes the i18n.properties file should look like the following:

      22 - i18.png

 

Writing the app controller

 

Next we need to write the app business logic. The business logic will be written inside the app controller.

Our controller will do the following:


  • Execute an HTTP request to Open Weather API and query the forecast for the next 16 days in London
  • Map the query results into our data model
  • Update (render) the view

 

Our controller should contain the following functions:

 

  • onInit -  a function that will be called when the controller will be created
    17 - onInit.png
    the onInit simply call to the _loadForecast function

  • _loadForecast - execute an ajax request to the Open Weather API and get the forecast for the next 16 days in London
    18 - loadForecast.png
    the _loadForecast do the following:
    • Build the URL and the URL parameters with the following data
      • City is London (q = "London")
      • Units are celsius (units = "metric")
      • Query the forecast for the next 16 days (cnt = 16)
      • Date format is json (mode = "json")
      • App id - if you have your own app id (signup and login is required) then you can specify it here otherwise you can use this one
    • Execute ajax request to the Open Weather API ($.get) with the relevant parameters
    • If we got results (.done()) we call the _mapResults function to map the results to our data model
    • if the request failed (.fail()...) we show an error message to the user

    • _mapResults - map the results from the ajax response to the data model
      19 - map results.png
    • This function get the query results as parameter and update the data model. this mapping is required because we must use a model who fits the data binding that we defined in view



  • _formatDate - format the date into string

    20 - format date.png

 

After you write the code to all the functions which describe above the main.controller.js file should look like the following:

 

21 - controller 1.png21 - controller 2.png

21 - controller 3.png

 

Run the app !

 

The last thing that left to do now is to run the app.

In order to run the app select the index.html file and click on the Run button (at the top)

 

23 - run.png

After you click on the run button a new tab will be opened and you will be able to see the app running.

If the app is not running you can check in the console what went wrong and if you still didn't manage to figure it our then you can clone the following GIT repository https://github.com/ranhsd/OpenWeatherSample.git into your WebIDE and run it.

 

That's it!

 

Ran.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

m

Viewing all 789 articles
Browse latest View live


Latest Images