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

Displaying Database Table Contents Dynamically using SAPUI5(SAP PORTAL APPLICATION)

0
0

In this blog, I want to explain you how you can display dynamic  table content and table layout from database table with SAPUI5. But I will not share java code, i will only share json data which i prepare in java code. First,  we’ll read the table names and fill into the combobox; then, we’ll show the table content of the selected table name from combobox.

We have Servlet that returns table names and table content as json format.

  • Table Names json :
{"tables":[{"id":"-1","name":"Select Table"},{"id":"ZDTY_CUSTOMER","name":"ZDTY_CUSTOMER"},{"id":"ZDTY_PERSON","name":"ZDTY_PERSON"},{"id":"ZHVL_REQUIREMENT","name":"ZHVL_REQUIREMENT"},{"id":"Z_IZINTALEPLERI","name":"Z_IZINTALEPLERI"},{"id":"Z_IZIN_FORM","name":"Z_IZIN_FORM"},{"id":"Z_IZIN_FORM_TABLE","name":"Z_IZIN_FORM_TABLE"},{"id":"Z_USERINFO","name":"Z_USERINFO"},{"id":"Z_USER_DETAIL","name":"Z_USER_DETAIL"},{"id":"Z_USER_INFO","name":"Z_USER_INFO"},{"id":"Z_USER_INFO_2","name":"Z_USER_INFO_2"},{"id":"Z_USER_INFO_3","name":"Z_USER_INFO_3"}]}
  • Table Content json :
{"message":"Success","content":[{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"1"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"2"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"3"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"4"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"5"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"6"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"7"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"8"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"9"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"10"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"11"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"12"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"13"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"14"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"15"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"16"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"17"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"18"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"19"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"20"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"21"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"22"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"23"},{"CUSTNAME":"deneme1","CUSTTEL":"deneme2","CUSTID":"24"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"25"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"26"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"27"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"28"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"29"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"30"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"31"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"32"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"33"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"34"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"35"},{"CUSTNAME":"Deneme","CUSTTEL":"Deneme","CUSTID":"36"}],"columns":[{"name":"CUSTID"},{"name":"CUSTNAME"},{"name":"CUSTTEL"}],"tname":"ZDTY_CUSTOMER"}

We have index.jsp and our code is here :

<%@pagelanguage="java"contentType="text/html; charset=UTF-8"

    pageEncoding="UTF-8"%>

<!DOCTYPEhtmlPUBLIC"-//W3C//DTD HTML 4.01 Transitional//EN""http://www.w3.org/TR/html4/loose.dtd">

<html>

<head>

<metahttp-equiv="Content-Type"content="text/html; charset=UTF-8">

<title>SAPUI 5</title>

<metahttp-equiv="X-UA-Compatible"content="IE=edge">

<script         src='/sapui5latest/resources/sap-ui-core.js'

                        type="text/javascript"

                        id="sap-ui-bootstrap"

                        data-sap-ui-theme="sap_bluecrystal"

data-sap-ui-libs="sap.ui.commons,sap.ui.table,sap.m">

</script>

<script>

                        var tablesModel = new sap.ui.model.json.JSONModel("/irj/servlet/prt/portal/prtroot/demo.sap.com~ui5~omer~tables.ReadTableServlet");

                        var tableContent = new sap.ui.model.json.JSONModel();                       

                        jQuery.sap.registerModulePath("ui5code", "/demo.sap.com~ui5~omer~tables/ui5code");

                        var app = new sap.m.App("myApp");

                        app.setInitialPage("idEklePage");

                        var view = sap.ui.view(

                                   { id:"idEklePage",

                                     viewName:"ui5code.appview",

                                     type:sap.ui.core.mvc.ViewType.JS

                                    });

                        view.placeAt("area");                   

</script>

</head>

<body>

<divid="area"></div>

</body>

</html>





 


We have two javascript file (view and controller files) appview.view.js and appview.controller.js. They are in ui5code folder.

 

appview.view.js file code :

sap.ui.jsview("ui5code.appview", {      /** 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 ui5desk.appview      */      getControllerName : function() {            return "ui5code.appview";      },      /** 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 ui5desk.appview      */      createContent : function(oController) {                        var mainFormLayout = new sap.ui.commons.layout.MatrixLayout();              mainFormLayout.setLayoutFixed(false);             var selectionLayout = new sap.ui.commons.layout.MatrixLayout();             selectionLayout.setLayoutFixed(false);             var sel_tables = new sap.m.Select("tablesId", {                    change : oController.getContent                });             sel_tables.setModel(tablesModel);             var item_sel_table = new sap.ui.core.Item({ key: "{id}", text: "{name}" });             sel_tables.bindItems("/tables", item_sel_table);             sel_tables.setSelectedKey(-1);              selectionLayout.createRow(                        new sap.m.Label({ text: "Table Name", width: "220px", required: true }),                        sel_tables);             mainFormLayout.createRow(selectionLayout);                       var table = new sap.m.Table("idTable",{                      growing: true,                    growingThreshold: 5,                    headerToolbar : new sap.m.Toolbar({                        content : [ new sap.m.Label({                            text : "{/tname}"                        })                        ]                    }),                    columns : [ new sap.m.Column({                        width : "2em",                        header : new sap.m.Label({                            text : "Column Name"                        })                    })                    ]                });                        table.setModel(tableContent);             mainFormLayout.createRow(table);                    return mainFormLayout;                   }    
});

appview.controller.js File code:

 

sap.ui.controller("ui5code.appview", {
/**
* Called when a controller is instantiated and its View controls (if available) are already created.
* Can be used to modify the View before it is displayed, to bind event handlers and do other one-time initialization.
* @memberOf ui5desk.appview
*/      onInit: function() {                },      getContent : function(oEvent) {                 var table = sap.ui.getCore().byId("idTable");            table.removeAllColumns();            var colitems = new sap.m.ColumnListItem();            var tablename = oEvent.getParameters().selectedItem.getText();            $.ajax({                type: 'get',                url: '/irj/servlet/prt/portal/prtroot/demo.sap.com~ui5~omer~tables.ReadTableServlet',                dataType: 'json',                data: {                              tablename: tablename                  },                 success: function(data) {                                      tableContent.setData(data);                                      for(var i = 0 ; i < data.columns.length ; i++)                    {                          var column = new sap.m.Column({                                    header : new sap.m.Label({                                        text : data.columns[i].name                                    })                                });                          table.addColumn(column);                          colitems.addCell(new sap.m.Text({                                    text : '{'+data.columns[i].name+'}'                                                            }));                                            }                    table.bindItems("/content", colitems);                                                                       },                error: function(data) {                    alert('fail');                }            });          
} 
/**
* Similar to onAfterRendering, but this hook is invoked before the controller's View is re-rendered
* (NOT before the first rendering! onInit() is used for that one!).
* @memberOf ui5desk.appview
*/
//    onBeforeRendering: function() {
//
//    },
/**
* Called when the View has been rendered (so its HTML is part of the document). Post-rendering manipulations of the HTML could be done here.
* This hook is the same one that SAPUI5 controls get after being rendered.
* @memberOf ui5desk.appview
*/
//    onAfterRendering: function() {
//
//    },
/**
* Called when the Controller is destroyed. Use this one to free resources and finalize activities.
* @memberOf ui5desk.appview
*/
//    onExit: function() {
//
//    }
});

Then we deploy the project to portal. And we can see result as below :

 

TableViewer1.png

TableViewer2.png


SAPUI5 working with offline data using jQuery.sap.storage

0
0

HTML5 brought to us the possibility to work offline without very complex solutions. We can make websites and webapps which can work 100% offline with few effort.

There are many components and many ways to make our webapps able to work without internet connection. To store data and make it available offline, we can basically use:

 

HTML5 Offline Technologies

  • Web Storage simply provides a key-value mapping, e.g. localStorage["name"] = username;. Unfortunately, present implementations only support string-to-string mappings, so you need to serialise and de-serialise other data structures. You can do so using JSON.stringify() and JSON.parse().
  • Web SQL Database gives you all the power - and effort - of a structured SQL relational database.
  • Indexed Database is somewhere in between Web Storage and Web SQL Database. Like Web Storage, it's a straightforward key-value mapping, but it supports indexes like those of relational databases, so searching objects matching a particular field is fast; you don't have to manually iterate through every object in the store.
  • File Access is an API for reading file content in JavaScript. Given a set of files the user has added to a "file" input element, you can read the content of the file or reference it as a URL, e.g. if the user has specified an image file, you can show the image. There are also proposals underway for file writing capabilities.

 

 

In the SAPUI5 framework we have a component which manipulates the HTML5 Web Storage object. This component is jQuery.sap.storage and is this one that I'm going to show you how to use.

Why this one?

  • It's simple to understand and to use;
  • It's the only one which can be manipulated straight with SAPUI5;
  • It's supported for all modern browsers;
  • It's perfect to use with JSONModel, you can store all your Model in one entry.

 

Check the API for jQuery.sap.storage here:

https://sapui5.netweaver.ondemand.com/sdk/#docs/api/symbols/jQuery.sap.storage.html

 

I won't explain the HTML5 Web Storage object in details, for further information go through the links below:

http://www.w3schools.com/html/html5_webstorage.asp

http://www.html5rocks.com/en/features/storage

 

For now, we just need to know that the limit for Web Storage is 5 MB, data is stored as string in name/value pairs and there are two types of Storage:

  • Local Storage - stores data with no expiration date, you can close the browser and data still there (jQuery.sap.storage.Type.local in UI5);
  • Session Storage - stores data for one session, if you close the browser (or tab) data is lost (jQuery.sap.storage.Type.session in UI5).

 

 

These are the main methods for Web Storage in UI5.

 

//Get Storage object to use
oStorage = jQuery.sap.storage(jQuery.sap.storage.Type.local);
//Get data from Storage
oStorage.get("myLocalData");
//Set data into Storage
oStorage.put("myLocalData", oData);
//Clear Storage
oStorage.clear();

 

 

Here you can check an application using jQuery.sap.storage.

 

https://077e7aad3963c58ca664a8cd5b57ce370a73b848.googledrive.com/host/0B2gJUv6a_V1dUTZtYVFTTDZsbXM/storage.html

 

<!DOCTYPE html><html><head><meta http-equiv="X-UA-Compatible" content="IE=edge" /><meta charset="UTF-8"><meta name=viewport content="width=device-width, initial-scale=1"><meta name="author" content="Mauricio Lauffer"><title>Storage Test</title><script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js" id="sap-ui-bootstrap"  data-sap-ui-libs="sap.m" data-sap-ui-theme="sap_bluecrystal"></script><script type="text/javascript">  var data = {  "Collection" : [ {  "id" : "1"  } ]  };  //Create Model  var oModel = new sap.ui.model.json.JSONModel();  oModel.setData(data);  //Storage  jQuery.sap.require("jquery.sap.storage");  oStorage = jQuery.sap.storage(jQuery.sap.storage.Type.local);  //Check if there is data into the Storage  if (oStorage.get("myLocalData")) {  console.log("Data is from Storage!");  var oData = oStorage.get("myLocalData");  oModel.setData(oData);  }  //Create Elements  var oList = new sap.m.List("localStorage");  var oBtn1 = new sap.m.Button({  icon : "sap-icon://add",  text : "Add to Model and Storage",  press : function() {  var oNew = {  id : $.now()  };  var oData = oModel.getData();  oData.Collection.push(oNew);  oModel.refresh(true);  oStorage.put("myLocalData", oData);  }  });  var oBtn2 = new sap.m.Button({  icon : "sap-icon://delete",  text : "Clear Storage",  press : function() {  oStorage.clear();  }  });  var oPage = new sap.m.Page("page1", {  title : "Storage Test",  content : [ oList ],  subHeader : new sap.m.Bar({  contentRight : [ oBtn1, oBtn2 ]  })  });  //Create Application  var oApp = new sap.m.App("myApp");  oApp.setModel(oModel);  oApp.addPage(oPage);  oApp.placeAt("content");  //Binding  oList.bindItems("/Collection", new sap.m.StandardListItem({  title : "{id}",  description : "Local Storage"  }));</script></head><body class="sapUiBody" role="application">  <div id="content"></div></body></html>

 

 

 

When you access the app for the first time there is nothing into Local Storage area and it's shown just one item on screen.

This item come from a variable (var data) defined in the app.

 

sto1.png

 

 

After to press the "Add" button, we have one more item on screen and now we have our first entry into Local Storage Area.

You can check it out on JavaScript's console.

 

sto2.png

 

 

After have pressed the "Add" button more few times, I refreshed the page (CTRL+F5) and the Model was filled with data from the previous Local Storage entry.

Check the message "Data is from Storage" on JavaScript's console.

 

sto5.png

 

 

 

You can do more, a lot more. This is just the first step with offline data in UI5 apps.

How I said at the beginning, you can use many others approaches to make your data offline.
For a full offline experience, you should use Appcache. It isn't a SAPUI5 component, it's an HTML5 object.

There are few blogs about it here and lots of pages out there. You can check the links below.

 

http://www.w3schools.com/html/html5_app_cache.asp

http://www.html5rocks.com/en/tutorials/appcache/beginner/

How to create an Android PhoneGap plugin for UI5 Mobile

0
0

This post explains how we can create an Android PhoneGap plugin for SAPUI5 mobile app to achieve certain native functionality. Let’s say we have a user of SAPUI5 mobile app who travels across places to collect transaction data from different vendors where there is no proper network, so he/she wants to maintain the data locally in a device log file and when he connects to network the same transaction data should be read from the log file and uploaded to the server, this log file can be referred anytime offline or even could be shared with others as an attachment in mail.

SAPUI5 being a client side UI library doesn’t have access to create/maintain a file locally in the device. For the same reason we need to use hybrid web container framework PhoneGap. PhoneGap provides standard APIs for certain functionalities and Native Plugin development capability. By creating PhoneGap plugins we can interact in a more detailed manner with device features and functions that are not already exposed through the PhoneGap API.

The prerequisite for this post is the basic knowledge on Creating SAPUI5 Applications and fair idea on PhoneGap.

 

Step 1)Creating a SAPUI5 mobile Application

First create a simple SAPUI5 mobile application with just one input box and button on the UI to trigger the Plugin call (in our case this button will trigger the transaction in the app from UI5 side passing the value of amount entered in the input box and sends a method call to plugin for maintaining log, once the log is maintained in a local file by the plugin java code, it will return back the status to ui5).

DemoAppUI5.png

Step 2)Downloading Cordova

Download the latest version of Cordova from the Cordova site (preferably the zip format - cordova-3.4.0-src.zip), link below…

http://cordova.apache.org/

Extract the main folder (cordova-3.4.0) and then the subfolder (Cordova-android) and place the same in C:\ drive

 

Step 3)Creating the Android Cordova package

Open Command prompt and navigate to the below link

Cd C:\cordova-3.4.0\cordova-android\cordova-android\bin

Then give the command - create D:\PhoneGap\demoapp org.sample DemoApp and hit Enter, This will create a DemoApp with the package org.sample in the location D:\PhoneGap\demoapp

Cordova package.png

Inside the location D:\PhoneGap\demoapp you can find the folder CordovaLib\src copy the contents of this src to the main src folder D:\PhoneGap\demoapp\src

 

Step 4) Setting up the project in Eclipse

The following step requires the Eclipse installed with Android SDK and ADT plugins for the development of Android native app.

Open eclipse and import the DemoApp project (New->other->Android->Android project from existing code), exclude the CordovaLib sub project since we have already copied the contents of this src folder to the main DemoApp src folder.

Eclipse android project.png

Copy the contents from the SAPUI5 project created before to the Android project assests/www folder (index.html, views, and controllers)

DemoApp.png

Include a reference in the head tag of the document index.html to the Cordova and index JavaScript file.

 

<script type=”text/javascript” src=”cordova.js”></script><script type=”text/javascript” src=”js/index.js”></script>


Step 5) Creating a Plugin (JS)

Create a new JavaScript file in the assets/www directory called MyPlugin.js and place the following code at the top of the new file:

 

var MyPlugin = function(){};
MyPlugin.prototype.savelog = function(message, successCallback, errorCallback)
{
try{       
cordova.exec(successCallback,errorCallback,’MyPlugin’,’savelog’,message);
}
catch(e){}
};

Include a reference in the head tag of the document index.html to the newly created plugin JavaScript file.

 

<script type=”text/javascript” src=”MyPlugin.js”></script>

Below this, add a new script tag block, inside of which place the deviceready event listener and savelog method. The code to be added is given below.

 

<script type=”text/javascript”>        var onDeviceReady = function(){};        function savelog(amount)        {            var msg = window.plugins.MyPlugin.savelog(amount,                                    function(sMessage)                                     {                                    return sMessage;                                    },                                    function(eMessage)                                     {                                    return sMessage;                                    }                        );                        return msg;        }        function init()        {            document.addEventListener(“deviceready”,onDeviceReady,true);        }</script>

Call the init() function in the onLoad of body

 

<body onLoad=”init();” class=”sapUiBody” role=”application”>

Firstly, we define the class name for our JavaScript plugin, and then create the first method we will invoke called savelog.

Add the following code to the bottom of the file to load the MyPlugin class into the window.plugins object

 

if(!window.plugins) {            window.plugins = {};
}
if (!window.plugins.MyPlugin) {
window.plugins.MyPlugin = new MyPlugin();
}


Step 6) Creating a Plugin (Java)

Create a new Java class file in your project by accessing File|New|Class from the main Eclipse menu. You can also access the wizard by selecting File|New|Other from the main menu and finding the Java class option in the list, as shown in the following screenshot:

The New Java Class wizard will open to help you complete this task. Provide the reverse domain format package name, and set the class name to MyPlugin. As we want to hook into the Cordova framework, we will also make sure it extends the org.apache.cordova.CordovaPlugin class, which is part of the Cordova core API.

Click on the Finish button to complete the wizard. The new Java class file will now be open in your Eclipse editor window.  Let’s now add the native code for our plugin. We’ll begin by wrapping our code in a try/catch block to trap and handle any errors.

We’ll qualify the action value sent through to the plugin to ensure we have a valid method to run. In this case, we’ll check to make sure that it matches savelog. Path of the log file is maintained in the code as /sdcard/Apps/logs.txt,

The full code is given below.

 

package com.sample;
import org.apache.cordova.CordovaPlugin;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import org.json.JSONException;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
public class MyPlugin extends CordovaPlugin {            @Override            public boolean execute(String action, String args, CallbackContext callbackContext) throws JSONException             {                        boolean stat = false;                        if (“savelog”.equals(action)) {                                     try {                                                File file = new File(“/sdcard/Apps/log.txt”);                                                boolean fileCreated;                                                if (file.exists()) {                                                            fileCreated = true;                                                }                                                else                                                {                                                            fileCreated = file.createNewFile();                                                }                                                if(fileCreated)                                                {                                                            PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(“/sdcard/Apps/log.txt”,true)));                                                            out.println(args);                                                            out.close();                                                }                                                else                                                {                                                            String result = “Internal Error”;                                                            PluginResult.Status status = PluginResult.Status.ERROR;                                                            PluginResult pluginResult = new PluginResult(status, result);                                                            callbackContext.error(result);                                                            stat = false;                                                            return false;                                                }                                                String result = “Transation saved”;                                                PluginResult.Status status = PluginResult.Status.OK;                                                PluginResult pluginResult = new PluginResult(status, result);                                                callbackContext.success();                                                stat = true;                                                return true;                                                                    } catch (Exception e) {                                                String result = e.getMessage();                                                PluginResult.Status status = PluginResult.Status.ERROR;                                                PluginResult pluginResult = new PluginResult(status, result);                                                callbackContext.error(result);                                                stat = false;                                                return false;                                    }                        }                        return stat;            }
}


Step 7) Mapping our plugin and Maintaining the uses permission

Before we can run the application, we need to add a mapping to our plugin within the Cordova config.xml file in the location res/xml/. Right-click on the file and select Open With Text Editor. Locate the plugins section and add a reference to our plugin within the following node:

 

<feature name=”MyPlugin”><param name=”android-package” value=”com.sample.MyPlugin” /></feature>

Also don’t forget to add the uses permission in the AndroidManifest.xml for creating and writing a file in the external storage and to access the SAPUI5 libraries.

 

<uses-permission android:name=”android.permission.INTERNET” /><uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />

Ideally for our use case the INTERNET permission is not applicable since the user mainly wants this functionality to work in remote parts by offline mode, for the same we also have to package the required SAPUI5 libraries in to the app resources instead of accessing the same from online, we will see about packaging the required UI5 library into the app in the following posts.

 

Step 8) Running our App

Let’s test our application and make sure we get a response from the plugin. Right-click on the main project folder and select Run as Android Application from the context menu to launch the application on the emulator. Here is the final output of the App running in mobile.

Final DemoApp.png

The complete project structure is as shown below

Complete project.png

 

How it works…

We created a JavaScript file to hold our client-side method calls and to handle success or error call-backs. We then created the native portion of the plugin, which extended the org.apache.cordova.CordovaPlugin class, thereby providing us with access and the ability to communicate between the JavaScript and native code.

Our JavaScript code called the cordova.exec method to invoke methods within our custom class:

 

cordova.exec( 
successCallback, 
errorCallback, 
'MyPlugin', 
'savelog', 
[message] 
); 

The exec () method accepts the following parameters:

Success: The success call-back function, which will run following a successful response from the plugin.

Error: The error call-back function, which will run following an unsuccessful operation and response from the plugin.

Service: This is mapped to the name of the native plugin class.

Action: The name of the action within the custom class to call and invoke.

Arguments: This is an optional parameter that allows you to send through data in an array, which can then be processed and used by the custom class.

The cordova.exec JavaScript method then invokes the execute function on the corresponding native plugin class.

The complete codes are given below.

 

Index.html

<!DOCTYPE html><html>    <head>        <meta charset=”utf-8” />        <meta name=”format-detection” content=”telephone=no” />        <meta name=”viewport” content=”user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi” />        <meta http-equiv=”X-UA-Compatible” content=”IE=edge”>                        <meta http-equiv=’Content-Type’ content=’text/html;charset=UTF-8’/>                        <script src=”https://sapui5.netweaver.ondemand.com/sdk/resources/sap-ui-core.js”                                                id=”sap-ui-bootstrap”                                                data-sap-ui-libs=”sap.m”                                                data-sap-ui-theme=”sap_bluecrystal”>                        </script>                        <script>                                sap.ui.localResources(“demoappui5”);                                 var app = new sap.m.App({initialPage:”idmainView1”});                                  var page = sap.ui.view({id:”idmainView1”, viewName:”demoappui5.mainView”, type:sap.ui.core.mvc.ViewType.XML});                                    app.addPage(page);                                    app.placeAt(“content”);                        </script>        <link rel=”stylesheet” type=”text/css” href=”css/index.css” />        <title>DemoApp</title>        <script type=”text/javascript” src=”cordova.js”></script>        <script type=”text/javascript” src=”js/index.js”></script>        <script type=”text/javascript” src=”MyPlugin.js”></script>        <script type=”text/javascript”>        var onDeviceReady = function(){};        function savelog(amount)        {            var msg = window.plugins.MyPlugin.savelog(amount,                                    function(sMessage)                                     {                                    return sMessage;                                    },                                    function(eMessage)                                     {                                    return sMessage;                                    }                        );                                    return msg;        }        function init()        {            document.addEventListener(“deviceready”,onDeviceReady,true);        }        </script>        <script>                   sap.ui.localResources(“demoappui5”);                   var app = new sap.m.App({initialPage:”idmainView1”});                    var page = sap.ui.view({id:”idmainView1”, viewName:”demoappui5.mainView”, type:sap.ui.core.mvc.ViewType.XML});                                                app.addPage(page);                                                app.placeAt(“content”);                        </script>    </head>    <body onLoad=”init();” class=”sapUiBody” role=”application”>        <div id=”content”></div>    </body></html> 


mainView.view.xml

<core:View xmlns:core=”sap.ui.core” xmlns:mvc=”sap.ui.core.mvc” xmlns=”sap.m”                        controllerName=”demoappui5.mainView” xmlns:html=”http://www.w3.org/1999/xhtml”>            <Page title=”DemoApp”>                        <content>                                    <Input id=”amount” type=”Text”></Input>                                    <Button press=”logHandler” text=”Save Offline (plugin call)”/>                                    <Button press=”sync” text=”Sync Data”/>                        </content>            </Page></core:View>


mainView.controller.js

sap.ui.controller(“demoappui5.mainView”, {            logHandler: function(){                        var amt = this.oView.byId(“amount”).mProperties.value;                        //do your functionality here                        var status = savelog(amt);                        this.oView.byId(“amount”).mProperties.value = “”;                        if(status == “OK”)                        {                                    sap.m.MessageToast.show(“Transaction log saved”);                        }                        else                        {                                    sap.m.MessageToast.show(“Transaction log failed; ” + status);                        }            }
});

 

I hope this post would be helpful to you all, feel free to comment for any queries. Thank you.

Google Maps library for UI5

0
0

There are a number of map providers available to use with UI5, none of them seemed to me to be as simple to use as Google Maps, so I wrote a library.

map1.png

 

Getting Started

Goto OpenUI5 Googlemaps Library Github page, download and install the library


Include the library


sap.ui.getCore().loadLibrary("openui5.googlemaps", "../openui5/googlemaps/");

 

Add a openui5.googlemaps control to your page

 

 

<?xml version="1.0" encoding="UTF-8" ?><mvc:View xmlns:mvc="sap.ui.core.mvc"    xmlns:gmaps="openui5.googlemaps"    controllerName="sampleController">    <gmaps:Map height="250px" zoom="12" lat="-33.895" lng="151.275">        <gmaps:markers>            <gmaps:Marker lat="-33.895" lng="151.275" info="Bondi Beach" />        </gmaps:markers>    </gmaps:Map></mvc:View>

 

Its as simple as that.

 

The openui5.googlemaps library supports Maps, Markers, Polylines and Polygons.

It also has Location detection and the ability to add an API key.

 

Along with the library there are also a number of sample applications to help get you started.

map2.png

The library if FOSS, contributions welcome, any issues please report through sapui5  - Stack Overflow

 

Enjoy

Integrating UI5 with Python

0
0

In this blog post we will learn how we can integrate UI5 with Python Django framework and deploy the application in the Red Hat Cloud Platform.

 

In my previous blog (How to create an Android PhoneGap plugin for UI5 Mobile) we have seen how can we create an Android plugin to save the text file locally from UI5 Mobile, as a next step we will create a simple server application where we can upload the same text file which we stored from android app to read transaction data and update our server database table.

 

Red Hat Cloud Platform (www.openshift.com) provides both free and enterprise PAAS and support for various technologies like Java, Php, Perl, Python, Ruby, Node.js. For this blog we will use the free services.  The prerequisite for this blog is basic knowledge on Git, UI5 and Python Django framework.

 

 

Creating an OpenShift Account:

 

First let’s create an account in the Red Hat Cloud Platform (www.openshift.com) providing basic details, activate your account by clicking on the email verification. Now Add a new application in your openshift cockpit clicking on Add Application under the Applications tab. Choose the technology under ‘browse by tag’ which you want for this application (which is also called as Cartilages in the world of openshift) we will choose the latest version of python with django - Django 1.6 and Python 3 on OpenShift.

django 1.6.png

Give the name for your application, I am using “DemoAppServer” and If you already have git repo with active code you can connect the same here by providing the valid git repo link in source code field, for now I am continuing with the standard Openshift Python Git repo link(https://github.com/rancavil/django-py3-openshift-quickstart.git) to install django and also if you want the application to be scalable , you can choose the scalable option during this step and click on Create Application.

 

Openshift creates a new git repo for you Application with the copy of standard git python repo which we have provided in the previous step.

making code changes.png

As a next step to continue with your development you need to clone the git repo which Openshift had created for your application to your local machine. For the same go to settings tab in OpenShift cockpit and update your ssh public key. OpenShift uses a public key to securely encrypt the connection between your local machine and your application and to authorize you to upload code.

 

 

Installing Git Bash and Connecting to OpenShift:

 

In this step we will see how we can create ssh key in your machine to connect with your Openshift account. To create the ssh key first download and install Git Bash from the location (http://git-scm.com/downloads).

 

While installing Enable the ‘Git Bash Here’ option and

gui bash here.png

‘Use Git from Git Bash only’ then finish the installation. The screenshots for both the above two options are attached.

bit bash only.png

Once the installation is completed, Open your Git Bash and give the following command

ssh-keygen -t rsa -C “your_email@example.com

 

Which creates a new ssh key, using the provided email as a label, Generating public/private rsa key pair.

 

Enter file in which to save the key (c:\Users\<your administrator>\.ssh\id_rsa): [Press enter]

Next, you'll be asked to enter a passphrase, then confirm the same.

ssh create masked.png

Go to the following location ‘C:\Users\<your administrator>\.ssh’ and you can find the file id_dsa.pub , right click that file and open with text editor, copy the contents and paste the same in the settings tab public key field of your Openshift account.

ssh pub masked.png

Now open Git Bash and git the command followed by the repository of your application to clone the same.

 

Git clone <your git repo link from openshift>

git clone demoserverapp.png

You can find the application code downloaded to the location

 

‘C:\Users\<your administrator>\<your application name>’

 

 

Developing our DemoAppServer:

 

Let’s open your application folder and see the following folder hierarchy,

openshift folder heir.png

We need to edit the urls.py file to redirect our call to the custom method in the views.py , I give the method name as home in the urls.py for the landing url, I would always prefer using the Python IDLE for editing .py files since the indentation as a significant role in python.

 

Now open Views.py, add a custom method home, find the code below. The following code will simple call the home.html file which I have mentioned in the template folder and send as a response to the http call.

 

Urls.py

from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
admin.autodiscover()
urlpatterns = patterns('',    # Examples:    url(r'^$', 'openshift.views.home', name='home'),    url(r'^upload', 'openshift.views.upload_file', name='upload_file'),    url(r'^create', 'openshift.views.create_table', name='create_table'),    url(r'^media/(?P<path>.*)$', 'django.views.static.serve', {'document_root': settings.MEDIA_ROOT, 'show_indexes':True}),    url(r'^admin/', include(admin.site.urls)),
)

The home.html (UI5 code) is mentioned below.

 

home.html

<!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="https://sapui5.netweaver.ondemand.com/sdk/resources/sap-ui-core.js"                id="sap-ui-bootstrap"                data-sap-ui-libs="sap.ui.commons,sap.ui.table"                data-sap-ui-theme="sap_bluecrystal">        </script>        <!-- add sap.ui.table,sap.ui.ux3 and/or other libraries to 'data-sap-ui-libs' if required -->        <script type="text/javascript">            var layout = new sap.ui.commons.layout.MatrixLayout();            layout.setLayoutFixed(false);            // create the uploader and disable the automatic upload            var oFileUploader = new sap.ui.commons.FileUploader({                name: "upload",                multiple: false,                maximumFileSize: 0.5,                mimeType: "text",                fileType: "txt",                uploadOnChange: false,                uploadUrl: "http://demoappserver-exaag.rhcloud.com/upload",                fileSizeExceed: function (oEvent) {                },                typeMissmatch: function (oEvent) {                },                uploadComplete: function (oEvent) {                    var sResponse = oEvent.getParameter("response");                    if (sResponse) {                        var myarray = [];                        var sRes = JSON.parse(sResponse);                        var myJSON = "";                        for (var i = 0; i < sRes.length; i++) {                            var item = {                                "amount": sRes[i],                            };                            myarray.push(item);                        }                        myJSON = JSON.stringify(myarray);                                       var oModel = new sap.ui.model.json.JSONModel();                        oModel.setData({modelData: JSON.parse(myJSON)});                        oTable.setModel(oModel);                        oTable.bindRows("/modelData");                    }            }});            //Define some sample data            var aData = [                {amount: "2000"}            ];            //Create an instance of the table control            var oTable = new sap.ui.table.Table({                title: "Transaction Data",                visibleRowCount: 10,                firstVisibleRow: 3,                width: "500px",                selectionMode: sap.ui.table.SelectionMode.Single            });            //Define the columns and the control templates to be used            var oColumn = new sap.ui.table.Column({                label: new sap.ui.commons.Label({text: "Amount credited (INR)"}),                template: new sap.ui.commons.TextView().bindProperty("text", "amount"),                width: "200px"            });            oTable.addColumn(oColumn);            //Create a model and bind the table rows to this model            var oModel = new sap.ui.model.json.JSONModel();            oModel.setData({modelData: aData});            oTable.setModel(oModel);            oTable.bindRows("/modelData");            layout.createRow(oFileUploader);            // create a second button to trigger the upload            var oTriggerButton = new sap.ui.commons.Button({                text:'Upload',                press:function() {                // call the upload method                oFileUploader.upload();            }            });            layout.createRow(oTriggerButton);            layout.createRow(oTable);            layout.placeAt("content");        </script>    </head>    <body class="sapUiBody" role="application">        <h1> DemoApp Server </h1>        <div id="content"></div>{% csrf_token %}    </body></html>

Open urls.py to add the custom method for uploading the text file and update the server datable, now open the views.py and paste the below mentioned code.

 

Views.py

from django.shortcuts import render_to_response
from django.core.context_processors import csrf
from django.views.decorators.csrf import csrf_exempt
from django.http import HttpResponse
from django import forms
import os
import sqlite3
import json
BASE_DIR = os.path.dirname(os.path.realpath(__file__))
MEDIA_ROOT = os.path.join(os.environ['OPENSHIFT_DATA_DIR'], 'media')
STATIC_ROOT = os.path.join(BASE_DIR, '..', 'static')
class UploadFileForm(forms.Form):    title = forms.CharField(max_length=50)    file  = forms.FileField()
def home(request):    return render_to_response('home/home.html')
@csrf_exempt
def upload_file(request):    cont = ""    conn = sqlite3.connect(os.path.join(os.environ['OPENSHIFT_DATA_DIR'], 'sqlite3.db'))    cursor = conn.cursor()    count = 0    for upfile in request.FILES.getlist('upload'):        for chunk in upfile.chunks():            cont = str(chunk)[2:][:-1]    val = []    val = str(cont).split("n")    conn = sqlite3.connect(os.path.join(os.environ['OPENSHIFT_DATA_DIR'], 'sqlite3.db'))    cursor = conn.cursor()    for el in val:        if el.find('r') > -1 :            cmd = "INSERT INTO transactiontb VALUES ('" + str(el)[:-3] + "')"        else:            cmd = "INSERT INTO transactiontb VALUES ('" + str(el) + "')"        cursor.execute(cmd)    conn.commit()    cmd = "SELECT * FROM transactiontb"    cursor = conn.cursor()    count = 0    lines = []    for res in cursor.execute(cmd):        lines.insert(count,str(res)[2:][:-3])        count = count + 1    conn.close()    return HttpResponse(json.dumps(lines))
def create_table(request):    conn = sqlite3.connect(os.path.join(os.environ['OPENSHIFT_DATA_DIR'], 'sqlite3.db'))    cursor = conn.cursor()    cmd = "CREATE TABLE transactiontb(amt text)"    cursor.execute(cmd)    conn.commit()    conn.close()    return HttpResponse("success")

This code will read the uploaded transaction data file , read the amount data and update the same in the database table (transactiondata), as a first step I had already created the database table transactiontb using the create_table method. Also for the time being I have used csrf_exempt , and added a small trick in the code to convert the binary data to string using string functions in python.

 

After updating the server, this method also returns the complete transaction data details back to UI5 in the JSON format and we will display the same in a table.

After making the code changes right click the folder ‘C:\Users\<your administrator>\<your application name>’ and click on the GUI Bash Here and continue with your git updation comments below.

 

Git add .

Git commit –m “my changes”

Git push


Find the sample text file with just amount over each line,

transactionData.png

Here is the OpenShift DemoAppServer link (http://demoappserver-exaag.rhcloud.com/).

 

The final output is here

FinalOutput.png

 

Feel free to comment for any queries, Thank you.

 

 

Kishore Kumar

Technology Consultant

Exa AG

Application data between different views

0
0

Hi,

 

        This blog is specially for the SAP UI5 beginners. It is related on 'How to control application data between different views at runtime'. If you want to use data between several views and/or controllers but you don’t want to use global javascript variable directly, you can use the SAPUI5 core to persist the data.

In this case you need to create an new attribute of type Object on the SAPUI5 core and persist the data in this attribute.

Now you are able to access this context data within the whole SAPUI5 application. Another big advantage of this approach will be that the context data is not visible directly for the outside world as a global object.

Below you will find an example how you can declare the context attribute and how you can use these in your SAPUI5 application.

index.html

<!DOCTYPE HTML>

<html>

<head>

<meta http-equiv=”X-UA-Compatible” content=”IE=edge”>  <script src=”resources/sap-ui-core.js”

id=”sap-ui-bootstrap”

data-sap-ui-libs=”sap.ui.commons”

data-sap-ui-theme=”sap_goldreflection”>

</script><script>

              sap.ui.getCore().AppContext = new Object();

              sap.ui.getCore().AppContext.Language = “Dutch”;

sap.ui.localResources(“exampleapplicationdatastore”);

var view = sap.ui.view({id:”idAppView1″, viewName:”exampleapplicationdatastore.AppView”, type:sap.ui.core.mvc.ViewType.JS});

view.placeAt(“content”);

</script>

</head><body class=”sapUiBody” role=”application”>

<div id=”content”></div>

</body>

</html>

AppView.View.js

sap.ui.jsview(“exampleapplicationdatastore.AppView”,{

getControllerName : function() {

return “exampleapplicationdatastore.AppView”;

},createContent : function(oController) {var oButton = new sap.ui.commons.Button(“btn1″, {text:sap.ui.getCore().AppContext.Language

});

return oButton;

}});

Now you can use the Application Context everywhere in the SAPUI5 application.


Reffered from: Code Snippets

 

  

                  

Primer on sap.m.Table

0
0

There's sap.m.Table and sap.ui.table.Table - two UI5 controls rendering a Table, but with substantial differences.

While sap.ui.table.Table holds all the bells and whistles for display on desktop devices, sap.m.Table (as the namespace suggests) is geared toward mobile devices. It inherits most of its functionality from the sap.m.List control, adding the "classic" columns and rows expected from a table.

 

For the purpose of this article and for better differentiation, sap.m.Table is referred to as m-table and sap.ui.table.Table as ui-table.

 

Building an m-table typically means defining cells (a.k.a any kind of controls) with corresponding columns, adding the cells to a row template:

// "cells"
var oName = new sap.m.Text({text: "{ProductName}"});
var oQty = new sap.m.Text({text: "{QuantityPerUnit}"});
var oPrice = new sap.m.Text({text: "{UnitPrice}"});
// corresponding columns
var oColName = new sap.m.Column({header: new sap.m.Text({text:"Product Name"}) });
var oColDesc = new sap.m.Column({header: new sap.m.Text({text:"Quantity per Unit"}) });
var oColPrice = new sap.m.Column({header: new sap.m.Text({text:"Unit Price"}) });
// row template
var oRow = new sap.m.ColumnListItem();
oRow.addCell(oName).addCell(oQty).addCell(oPrice);

Then, the m-table is instantiated together, along with adding the previously defined colums:

// table
var oTab = new sap.m.Table("oTab");
oTab.addColumn(oColName).addColumn(oColDesc).addColumn(oColPrice);

Binding data to the table can be done by using m-table's bindItems(), a convenience function for setting an aggregation binding to a UI5 control:

oTab.bindItems("/Products", oRow);

A substantial difference between ui-table and m-table is the fact, that m-table provides some predefined User Interaction modes that can be utilized to achieve three typical UX tasks of table design: selecting a single row, selecting multiple rows and deleting a row.

 

For that purpose, m-table offers the setMode() function that takes the sap.m.ListMode Enumeration as values:

oTab.setMode(sap.m.ListMode.Delete); // delete mode
oTab.setMode(sap.m.ListMode.MultiSelect); // multi-selection of rows
oTab.setMode(sap.m.ListMode.SingleSelectLeft); // left checkbox per row for singe selection of a row

 

(FTR: there's a couple more options to sap.m.ListMode)

 

Visually, this is what the different m-table-modes look like in the above mentioned sequence:

m-table-delete.png

 

m-table-multi.png

m-table-single.png

 

Note that the multi-select option also shows a checkbox in the column header to select/deselect all rows of the m-table.

 

Additionally, there's also dedicated events in order to react on user interation:

.attachSelectionChange() provides access to the selection/deselection of a row

.attachDelete() provides access to the deleted row

 

Utilizing core UI5-functionality, you can then access the selected/deselected/deleted row and/or items:

 

oTab.attachSelectionChange( function(oEvent) {    var oSelectedItem = oEvent.getParameter("listItem");    var sItemName = oSelectedItem.getBindingContext().getProperty("ProductName"); // access item via bound data
});

 

In summary, UI5's m-table provides both Visual Design Patterns and Interaction handlers for Tables on mobile devices.

 

No need for classic Design Patterns à la

ui-meh-table.png

any more that haul along a bunch of icons in every row of a table for the sole purpose of indicating interaction possibilities to the user.

Mask them with UI5's m-table Table Mode for cleaner and more simple UIs!

 

Here's a single-page-app on GitHub showcasing sap.m.table modes.

How to use Northwind OData service with SAP River RDE

0
0

I've received several requests about how to use the public Northwind OData service located at the address http://services.odata.org/V3/northwind/northwind.svc with SAP River RDE. I'm going to explain in this post how to do it.

 

I will go through the following steps:

 

  1. Download the metadata file
  2. Configure the destination
  3. Create the application
  4. Change the Component.js file
  5. Change the neo-app.json file
  6. Run the application

 

Let's go!

 

  1. First of all you need to download the metadata file from the Northwind service. You can do it by using Chrome and activating the inspector:
    1. Open Chrome
    2. Activate the inspector
    3. Navigate to the link http://services.odata.org/V3/northwind/northwind.svc/$metadata
    4. Switch back to the inspector, click on the Resources tab, right click on the $metadata file from the Frames --> ($metadata) --> $metadata branch and select Save as...ss01.jpg
    5. Save the file where you want for later use at step 3
  2. Configure the destination by going to your account.hanatrial.ondemand.com cockpit and creating a new destination in the following way:ss02.jpg
  3. Create a new application in SAP River RDE by using one of the templates which require data connection. In this example we are going to create a SAP Fiori Starter App. In the Data Connection section, click Browse button and select the metadata.xml you saved in step 1 and click on Next. Fill-up the template customization section and finish the rest of the wizard. Now the project is created.
  4. Change the Component.js file: open the Component.js file, edit it in the following way and save the file.ss03.jpg
  5. Change the neo-app.json file: edit the neo-app.json file by adding the following piece at the beginning of the file just after the opening of the routes section and save the file. ss04.jpg
  6. Finally you can run the application

 

You have successfully connected your SAP River RDE environment with the Northwind OData service.


Real Time GPS Tracker using SAP HANA XS, SAPUI5, Cordova Geolocation Plugin and OData

Issues with CSRF token and how to solve them

0
0

Lately, I was struggling with correct handling of this token. Since I found some misleading content here in community network, I would like to share with my findings.

 

 

What is CSRF, why do we use CSRF token and how long it is valid

CSRF (Cross-site request forgery) is type of attack, when attacker tries to send malicious requests from a website that user visits to another site where the victim is authenticated. Prevention from this attack is based on keeping security token during user's session and providing it with every modify operation (PUT, POST, DELETE). If the provided token is not correct, gateway responds with HTTP 403 ("Forbidden") return code. [1, 2]

 

The validity depends on your settings and SAP_BASIS release. In my case, I found out that the validity of token is set to 30 minutes.

"The validity of the CSRF token depends on the release of the ABAP component SAP_BASIS and on the activation of the security session management (which is controlled via the transaction SICF_SESSIONS on the granularity of SAP clients):

1. Release < 7.03/7.31 or the security session management is inactive: An own CSRF cookie gets generated (sap-XSRF_<SystemID>_<SAPClient>) and this CSRF token remains valid for 24 hours (86400 seconds).

2. Release >= 7.03/7.31, the validity is bound to the security session, which depends on the system parameter http/security_session_timeout value (see transaction RZ11 for details on this parameter). By default, the security session management is active in these releases." [3]

 

When you do not provide fresh security token with modify request, the user can end up with 403 error message and his recent entry in some form will be most likely lost. There are different ways how the token is handled.

 

 

1st issue - You are using ODataModel for modify operations and not calling refreshSecurityToken() method before them

You should be safe anyway. ODataModel has a parameter called bTokenHandling that takes care about token handling. I did not find information when openui5 started to support this functionality, but you can check it in debugger that after creating ODataModel instance, bTokenHandling is set to true by default.

So the outcome of this finding is that you do not need to use method refreshSecurityToken() unless you turn off bTokenHandling or you want to implement some special fuctionallity when refresh fails.

 

 

2nd issue - You are using datajs library and OData.request for your modify operations

There are several blog posts in SCN using this library. You should fetch CSRF token before every modify operation, if you want to prevent your user to see HTTP 403 response.

 

 

3rd issue - You are using external REST client for testing modify operation

If you do not provide the token, you will receive 403 HTTP Forbidden response with following message "CSRF token validation failed".

In this case, you need to first fetch CSRF token, adding header parameter X-CSRF-Token : Fetch, read its content from response parameter x-csrf-token and add it manually to header of your testing modify request.

csrf1.JPGcsrf2.JPG

 

4th issue - You are sending files to SAP Gateway using sap.ui.commons.FileUploader and you are getting 403 HTTP response - CSRF token validation failed

Unfortunately, there is no link between fileuploader and ODataModel, so fileuploader needs to handle token validation by itself. Same logic applies here as the previous issue. Unfortunately (again), there is no way how to set http header parameter for fileuploader, so you need to redefine it by yourself and change the logic as it is described in this post Re: FileUploader and X-CSRF-Token?.

 

 

Looking forward to your feedback, let me know if some of my assumptions are not correct.

 

References

[1] Cross-site request forgery - Wikipedia, the free encyclopedia

[2] https://help.sap.com/saphelp_nw74/helpdata/en/b3/5c22518bc72214e10000000a44176d/content.htm

[3] CSRF Protection - Connectivity - SAP Library

Read NFC tag using Kapsel & SAPUI5

0
0

This Blog explains about how to Integrate NFC Plug-in with Kapsel and how to read the NFC tag using SAPUI5 mobile application.for our understanding, entire process will be explained in five sections,

 

1) Kapsel Setup & Android Project Creation.

2) Add NFC plugin to Kapsel.

3) Import the project into Android Developer Tools.

4) Create the SAPUI5 front end to the application.

5) Read the NFC tag using the UI5 application.

 

1) Kapsel Setup & Android Project Creation

 

   Hybrid Mobile apps to get the native device functionality we have to use kapsel or Cordova,UI5 applications need to integrate with Apache Cordova API to render      screens inside the Cordova Container.Briefly explained the setup of Kapsel.Here we are going to see the check list for the setup.

 

Once the Node js installed on the machine,looks like below screen shot,CordovaInstall.jpg

once all the above prerequisites software are installed on our machines we need to execute the following commands sequentially.

 

  1. open the command prompt or if it is Mac machine go to terminal execute the command,

               npm install –g cordova

   2.  Now we have to create the Cordova Project

          2.1) Open the Command Prompt type the command :cordova create NfcTagReader com.example.nfctag "NfcTagReader"

                   above command cordova create will create Kapsel project with name 'NfcTagReader' and package name  'com.example.nfctag'

   CordovaCreate.png

     Execute the another command to add the different platform for this Cordova project, Cordova NFC Plugin will Supports Windows Phone 8,BlackBerry 10              and Android,but in our example we are creating Android project, because it has largest market using by android users.

     2.2) continue the command : cordova -d platform add android

 

2) Add NFC plugin to Kapsel

          2.1) Now Android project is ready to run the application on the mobile device, we have to add the project to the NFC plugin,

          2.2) Open the command prompt at NfcTagReader folder type the command : cordova plugin add https://github.com/chariotsolutions/phonegap-nfc

nfcpluginstall.jpg

 

3) Import the project into Android Developer Tools

     Import created Kapsel Project into ADT work space to generate the NFCTagReader.apk file, importandriod.jpg

 

4) Once the project imported and need to create UI5 view for this project,we have to create the SAPUI5 reference to the project to get the view inside the page component.Here is the detailed guide to create the project in UI5, In this example i have created the xml view in the bootstrap file,

<script src="https://sapui5.netweaver.ondemand.com/resources/sap-ui-core.js"

                 id="sap-ui-bootstrap"

                 data-sap-ui-libs="sap.m,sap.ui.commons"

                 data-sap-ui-theme="sap_bluecrystal">

</script>

 

  <script>

                 sap.ui.localResources("NfcTagReader");

                 var app = new sap.m.App({initialPage:"idTagReader"});

                 var page = sap.ui.view({id:"idTagReaderView",viewName:"NfcTagReader.NfcTagReader", type:sap.ui.core.mvc.ViewType.XML});

                      app.addPage(page);

                      app.placeAt("content");

  </script>

 

5) go to the created xml view and add the button to tigger the nfc event: <Button id="but1" text="Tap to get the NFC Id" tap="onTap"></Button>

 

6) Add the method to button event

controllerMethod.jpg

we are reached the end of our application, we have to connect the NFC enabled mobile device and deploy the application,one of the question here is how to identify the NFC tag to test the application, lot of NFC tags are available in the market, as well as we can see the most the bank cards will have the symbol "PayPass".

 

card1.jpg

Once the application is launched on the mobile device, we can see the UI5 screen with Button,AppRun.jpg

Tap on the button to initiate the NFC event to get the NFC Beam and touch the NFC enabled card with phone,

Screenshot_2014-07-15-12-23-34.png

Here we go the Message box will be displayed the NFC ID.

UI5 Control for Google Maps with Data Binding

0
0

In a previous post I used the Google Maps API to interact with the SAP HANA Geographic objects Aggregation of tables by geographic location using geo-spatial SAP HANA capacities, SAP UI5 and Google Maps,  this is a more advanced stage of the UI5 and Google Maps integration, now the map is included as a UI5 Control, where each layer of the elements to draw is an aggregation of the Map object, this allows to bind the data of a Model with markers, locations of a heatmap, or the path of a polygon or polyline, I shared the project on OpenUI5 Control for Google Maps.

 

The modules create the constructor for the Map control.

  • mexbalia.Maps.Map

and the constructors for the Elements which are elements of the aggregation Layers

  • mexbalia.Maps.HeatMap
  • mexbalia.Maps.Markers
  • mexbalia.Maps.Polygon
  • mexbalia.Maps.Polyline

each Layer has an aggregation Locations or Markers, the template used for the cloning of each row are created with the constructors

  • mexbalia.Maps.Marker
  • mexbalia.Maps.Location

the Layers of the Map are created like the columns in the sap.ui.table.Table control.

 

The next lines creates the Map used in this example http://christianlgr.github.io/GMaps-UI5/MapDemo.html .

//Loading of modules.  jQuery.sap.registerModulePath('mexbalia','src/');  jQuery.sap.require('mexbalia.Maps.Polygon');  jQuery.sap.require('mexbalia.Maps.MarkersLayer');  //Creation of the templates for the aggregations in the Layers  locationsTemplate = new mexbalia.Maps.Location({latitude:"{Latitude}",longitude:"{Longitude}"});  markersTemplate = new mexbalia.Maps.Marker({latitude:"{Latitude}",longitude:"{Longitude}"});  //Creation of the Map  Map = new mexbalia.Maps.Map();  //Creation of the layers Polygon and markersLayer  Polygon= new mexbalia.Maps.Polygon({locations:{path:"/Markers",template:locationsTemplate}});  markersLayer= new mexbalia.Maps.MarkersLayer({markers:{path:"/Markers",template:markersTemplate}});  //Insertion of the layers into the map  Map.insertLayer(markersLayer);  Map.insertLayer(Polygon);  //Setting of the model and placing in the <div> element  Modelo = new sap.ui.model.json.JSONModel();  Modelo.setData(LocationsData);  Map.setModel(Modelo);  Map.placeAt("map-canvas");

Screenshot from 2014-07-15 19:33:08.png

In this example the locations are bounded to a table, both bindings are two-way type, then any change in the table values affects the map markers and polygon locations automatically.

Bind sap.m.StandardListItem "Selected" Property from odata boolean Result "X"

0
0

I was trying to bindItems in a sap.m.List of sap.m.StandardListItem, but was not able to make sap.m.ListMode.MultiSelect selected if one parameter is coming "X". In filter if we use this boolean check then false results will not be shown in output. To show in a Dialog the list with selected StandardListItem, I used bindProperty and it works. Here is my code example:

Code Snippet

var itemTemplate = new sap.m.StandardListItem({

  title : "{SrvTaskDesc}", // string

  });

  itemTemplate.bindProperty("selected", "IsenbDisInd", function(bValue) {

     return bValue == "X" ? true : false;

  });

  retMethList = new sap.m.List({

  mode : sap.m.ListMode.MultiSelect,

  });

  url = location.protocol+"//"+dynamicHost+":"+dynamicPort+"/sap/opu/odata/XXX/XXXXXXX/";

  oModel = new sap.ui.model.odata.ODataModel(url, true);

  retMethList.setModel(oModel);

  params = ",C" + ","

  + sap.ui.getCore().getModel("userModel").getData().plant + ",,,,"

  + "";

  filter = new sap.ui.model.Filter("IAllparam", sap.ui.model.FilterOperator.EQ, params);

  retMethList.bindItems("/getGlobalTaskList",itemTemplate,null,[filter]);

  new sap.m.Dialog({

  title : "Sanjoy Saha", // string

  content : retMethList, // sap.ui.core.Control

  leftButton : new sap.m.Button({

  text : "CANCEL",

  type : sap.m.ButtonType.Reject,

  icon : sap.ui.core.IconPool

  .getIconURI("sys-cancel"),

  press : function() {

  this.getParent().close();

  }

  }),

  rightButton : new sap.m.Button({

  text : "SAVE",

  type : sap.m.ButtonType.Accept,

  icon : sap.ui.core.IconPool.getIconURI("save"),

  press : function() {

  this.getParent().close();

  }

  }),

  afterClose : [ function(oEvent) {

  var control = oEvent.getSource();

  }, this ]

  }).open();

 

 

Here IsenbDisInd is the field which is coming from odata as "X" or "" as output and based on that ListItem is selected or deselected.

Custom SAPUI5 Visualization Controls with D3.js

0
0

Over the last couple of months I have been playing with D3.js, the JavaScript visualization library that allows you to programmatically create SVG visualizations on the basis of a data set. I love how this allows me to think up how to visualize a particular dataset without any constraints of the capabilities of any charts and graph package included in whatever tool you would otherwise have used. I have since built out custom extensions in Lumira using D3.js, and when I started looking at SAPUI5, one of the first things I wanted to do was create my own D3.js SAPUI5 custom controls.

 

There have been other articles on including D3.js in SAPUI5 (most notably here and here), but they used an HTML template, rather than include it in a custom control that could be used largely like any other SAPUI5 control. Well, after a bit of puzzling and some help from a colleague who had built custom controls based on other SAPUI5 controls for a different project, I managed to figure it out, and through this blog, I hope to help you create your own.

 

This is one of the controls I created. You see it here included in a page, embedded within a <Panel> tag. It receives a data set of target, currently booked revenue and a forecast, and then shows the percentage of booked revenue and forecast against the target. We will focus here largely on the SAPUI5 custom control parts rather than the D3.js code, but the control is available for download at the bottom of this blog.

 

d3_custom_control.png

Building the Chart Control

Let’s create our custom control: create a new folder called “controls” inside the WebContent folder of your SAPUI5 application, and create a new JavaScript file. We’ll use the attached D3ChartTemplate.js as an example. In your own controls you should change the class names (and filename) to something a bit more descriptive so you know which is which, and typically you’d call your JavaScript file the same as the control (i.e. BarChart.js would contain BarChart and BarChartItem classes).

 

We start with a requirement to load the built-in third party D3 library and a declaration of the chart itself:

 

jQuery.sap.require("sap/ui/thirdparty/d3");

jQuery.sap.declare("sap.jaysdk.Chart");

 

Then, we need to define our ChartItem. This is used to map between what the chart expects and the dataset you are trying to visualize. You’ll see this once we get to instantiating the chart.

 

sap.ui.core.Element.extend("sap.jaysdk.ChartItem", { metadata : {

       properties : {

              "region" : {type : "string", group : "Misc", defaultValue : null},

              "budget" : {type : "string", group : "Misc", defaultValue : null},

              "bw" : {type : "string", group : "Misc", defaultValue : null},

              "forecast" : {type : "string", group : "Misc", defaultValue : null

       }

}});


We then set up the definition of the Chart itself:

 

sap.ui.core.Control.extend("sap.jaysdk.Chart", {

       metadata : {

              properties: {

                     "title": {type : "string", group : "Misc", defaultValue : "Chart Title"}

              },

              aggregations : {

                     "items" : { type: "sap.jaysdk.ChartItem", multiple : true, singularName : "item"}

              }

              ,

              defaultAggregation : "items",

              events: {

                     "onPress" : {},

                     "onChange":{}       

              }                   

       },

       …

}

 

You see here the ChartItem referenced. Once data is passed in, these will become our “items”.

 

We need to split the setup of the chart separately from the D3.js code, since we need to create the placeholder first, while the D3.js code will only run after rendering the HTML through the Chart’s onAfterRendering() function. So, let’s create the chart:

 

createChart : function() {

              /*

         * Called from renderer

         */

        console.log("sap.jaysdk.Chart.createChart()");

              var oChartLayout = new sap.m.VBox({alignItems:sap.m.FlexAlignItems.Center,justifyContent:sap.m.FlexJustifyContent.Center});

              var oChartFlexBox = new sap.m.FlexBox({height:"180px",alignItems:sap.m.FlexAlignItems.Center});

              /* ATTENTION: Important

         * This is where the magic happens: we need a handle for our SVG to attach to. We can get this using .getIdForLabel()

         * Check this in the 'Elements' section of the ChromeDevtools:

         * By creating the layout and the Flexbox, we create elements specific for this control, and SAPUI5 takes care of

         * ID naming. With this ID, we can append an SVG tag inside the FlexBox

         */

              this.sParentId=oChartFlexBox.getIdForLabel();

        oChartLayout.addItem(oChartFlexBox);

           

              return oChartLayout;

 

    },

 

We create a VBox and place a FlexBox inside of it. Then, as the comments already suggest, we get the magic. Rather than using a <div> tag or <span> tag that we write deliberately in an HTML file, we’re going to leverage the identifier of the FlexBox to attach our SVG to. This is what it looks like in the Chrome DevTools “Elements” section:

div_id.png


The “__box2” id is what we will use and is stored in this.sParentId.

 

We have a pretty standard renderer function, with the only difference that we call the createChart function.

 

renderer : function(oRm, oControl) {

              var layout = oControl.createChart();

 

        oRm.write("<div");

        oRm.writeControlData(layout); // writes the Control ID and enables event handling - important!

        oRm.writeClasses(); // there is no class to write, but this enables

              // support for ColorBoxContainer.addStyleClass(...)

           

        oRm.write(">");

        oRm.renderControl(layout);

        oRm.addClass('verticalAlignment');

 

        oRm.write("</div>");

    

   },


Finally, the Chart is completed in the onAfterRendering() function:

 

onAfterRendering: function(){

        console.log("sap.jaysdk.Chart.onAfterRendering()");

        console.log(this.sParentId);

              var cItems = this.getItems();

              var data = [];

              for (var i=0;i<cItems.length;i++){

                     var oEntry = {};

                     for (var j in cItems[i].mProperties) {

                oEntry[j]=cItems[i].mProperties[j];

            }                                

            data.push(oEntry);

        }

              //console.log("Data:");

              //console.log(data);

           

              /*

         * ATTENTION: See .createChart()

         * Here we're picking up a handle to the "parent" FlexBox with the ID we got in .createChart()

         * Now simply .append SVG elements as desired

         * EVERYTHING BELOW THIS IS PURE D3.js

         */

           

              var vis = d3.select("#" + this.sParentId);

           

              //Your D3.js code HERE

                     

       }

 

We get the “items” that were passed in containing our data, and read it into the data array. Once that has run, you have the dataset from your model in the chart and you are ready to build out your SVG. We can now attach to the <div> tag with the id we retrieved before using d3.select. After that, it is just standard D3.js code!

 

Using the Chart control

We can now try to use the chart in our SAPUI5 pages. We start with creating a container inside the Xxx.view.xml file:

 

<Panel>

<headerToolbar>

              <Toolbar>

                     <Labeltext="YTD Booked/Won and Forecast to Budget (Percentage)"/>

              </Toolbar>

       </headerToolbar>

       <FlexBoxid="ChartHolder"alignItems="Start"justifyContent="Center">

</FlexBox>

</Panel>

 

This creates the location that we will place our chart in. Now we need to add the chart to our Xxx.controller.js. We need start with declaring the Chart and the ChartItem. The resource path should be the path to your custom control relative to index.html and its name without the js extension. Notice that since the ChartItem is embedded in the controls/Chart.js file, its module path is controls/Chart. Again, for your own controls, use the same convention, but obviously a more descriptive name for your custom chart.


jQuery.sap.registerModulePath("sap.jaysdk.Chart", "controls/Chart");

jQuery.sap.require("sap.jaysdk.Chart");

jQuery.sap.registerModulePath("sap.jaysdk.ChartItem", "controls/Chart");

jQuery.sap.require("sap.jaysdk.ChartItem");

 

Next, we instantiate our chart, inside the onBeforeRendering() function (or a separate function call from within that event function). We find the ChartHolder FlexBox, create a ChartItem that maps the fields from the data in your model to the chart, and create a new chart (here with a path included). We then get a handle on the model and set the model to the chart. Finally, we add the chart to the FlexBox container.

 

varoChartHolder = this.byId("ChartHolder");

var oChartItem = new sap.jaysdk.ChartItem({region:"{region}", budget:"{budget}", bw:"{bw_ytd}", forecast:"{forecast}"});

/* new  chart */

var oChart = new sap.jaysdk.Chart({

       items: {path : "/regions", template : oChartItem}

});

           

var oModel = sap.ui.getCore().getModel("chart");

oChart.setModel(oModel);

oChartHolder.addItem(oChart);

 

And that’s it! Your chart should now be visible in your application, and can be embedded like any other control.

 

Attached below you'll find the D3ChartTemplate as well as the PerformanceToTargetComparison chart of which a screenshot is shown at the top of this blog. I have also included a JSON file with the sample data.

 

SAPUI5 is an excellent framework to quickly develop business applications, and using the techniques described here, you can now add any fancy visualization you would like. Happy hacking!

Dynamic Tab Creation in sap.ui.commons.TabStrip

0
0

Requirement is based on odata output show linked children tabs corresponding to the parent tab. These children numbers are dynamic depending upon parent's data configuration. Also we have to go each tab and give some inputs, then save all tabs together in one save. Also user can move to any tab, but entered data should not be lost. Now check the solution below: if(sap.ui.getCore().byId("idParentTabStrip") == null) {

  oTabStrip = new sap.ui.commons.TabStrip("idParentTabStrip", {  selectedIndex : 0, // int  tabs : [ new sap.ui.commons.Tab({  width : "100%", // sap.ui.core.CSSSize  content : [this.options.tileContainerObj], // sap.ui.core.Control  title : new sap.ui.core.Title({  text : "Parent", // string  icon : "sap-icon://task", // sap.ui.core.URI  }),   }) ],   select : [ function(oEvent) {  var resultData = null;  var callSuccess = false;  _self.syncChildWithParent(oEvent.getSource().getSelectedIndex());  _self.setIndexOfTab(oEvent.getSource().getSelectedIndex()-1);  if(_self.options.tabAlreadyClicked.indexOf("idChildTab"+_self.options.indexOfTab) >= 0){  } else {  _self.options.tabAlreadyClicked.push("idChildTab"+_self.getIndexOfTab());  var oTab = sap.ui.getCore().byId("idChildTab"+_self.getIndexOfTab());  if(oTab != null && sap.ui.getCore().byId("idBarCode") != null) {  var urlChildDetfromParent = location.protocol+"//"+dynamicHost+":"+dynamicPort+"/sap/opu/odata/XXX/XXX_XXX_XXX/getChildFromParent?$filter=IParentBarcode eq '"  + sap.ui.getCore().byId("idBarCode").getNumber()  + "'&$format=json";  jQuery.ajax({username: sap.ui.getCore().getModel("userModel").getData().username, password: sap.ui.getCore().getModel("userModel").getData().password,  url : urlChildDetfromParent,  enableJsonpCallback: true,  jsonpCallback : 'getJSON',  contentType : "application/json",  dataType: "json",  async: false,  complete: function(jqXHR,textStatus){  if(callSuccess){  data = resultData;  if(data.d.results.length > 0){  var i = _self.getIndexOfTab();  otab = sap.ui.getCore().byId("idChildTab"+i);  fieldsVal = data.d.results[i];  _self._buildMandatoryFieldsInTab(fieldsVal);  }  }  },  success: function(data, textStatus, jqXHR) {  callSuccess = true;  resultData = data;  }  });  }  }  }, this ]  });  }  var urlChildList = location.protocol+"//"+dynamicHost+":"+dynamicPort+"/sap/opu/odata/XXX/XXX_XXX_XXX/getChildList?$filter=IAllparam eq '"  + "WW,"+sap.ui.getCore().byId("idYYYcode").getNumber()+","+sap.ui.getCore().byId("idCCCType").getNumber()+","+sap.ui.getCore().byId("idDDDType").getNumber()  + "'&$format=json";  jQuery.ajax({username: sap.ui.getCore().getModel("userModel").getData().username, password: sap.ui.getCore().getModel("userModel").getData().password,  url : urlChildList,  enableJsonpCallback: true,  jsonpCallback : 'getJSON',  contentType : "application/json",  dataType: "json",  async: false,  success: function(data, textStatus, jqXHR) {  for (var i=0;i<data.d.results.length;i++) {  if(sap.ui.getCore().byId("idChildCat"+i) == null){  var oChildPanel = new sap.m.Panel("idChildPanel"+i, {  width : "100%",   height : "auto",   content : [            new sap.m.Text("idChildCat"+i,            {            text : data.d.results[i].ChildCat,            visible : false            }),            new sap.m.Text("idChildCatDesc"+i,            {            text : data.d.results[i].Description,            visible : false            })            ], // sap.ui.core.Control  });  var oChildTab = new sap.ui.commons.Tab("idChildTab"+i, {  width : "100%", // sap.ui.core.CSSSize  content : [oChildPanel], // sap.ui.core.Control  title : new sap.ui.core.Title({  text : data.d.results[i].ShortKey, // string  icon : "sap-icon://task", // sap.ui.core.URI  }), // sap.ui.core.Title  });  if(oTabStrip) {  oTabStrip.addTab(oChildTab);  }   }  }  }  });  sap.ui.getCore().byId(this.options.pageId).addContent(oTabStrip);

Also the other challenge was that if user inputs one field in any tab, then user has not to enter again in other tabs(parent or child) if fields are same, for that we have one small function named "syncChildWithParent". Prerequisite is common fields are already known here, but code can be changed for unknown matching fields and that part is left to you for comment. Code:

syncChildWithParent : function(index) {  if(sap.ui.getCore().byId("idParentTabStrip")){  oTabs = sap.ui.getCore().byId("idParentTabStrip").getTabs();  var idArray = ["idChildType",                "idChildThreadOutlet",                "idChildConn",                "idChildThreadInlet",                "idChildManu",                "idChildDate",                "idPartNo"];   for (var i = 0; i < idArray.length; i++) {  idString = idArray[i];  parentValue = "";  childValue = "";  parentValueUnit = "";  childValueUnit = "";  if(sap.ui.getCore().byId(idString)) {  parentValue = sap.ui.getCore().byId(idString).getNumber();  parentValueUnit = sap.ui.getCore().byId(idString).getNumberUnit();  }  for (var int = 0; int < oTabs.length; int++) {  if(sap.ui.getCore().byId(idString+int)) {  childValue = sap.ui.getCore().byId(idString+int).getNumber();  childValueUnit = sap.ui.getCore().byId(idString+int).getNumberUnit();  if (parentValue && parentValue != childValue && index > 0){  sap.ui.getCore().byId(idString+int).setNumber(parentValue);  sap.ui.getCore().byId(idString+int).setNumberUnit(parentValueUnit);  if (sap.ui.getCore().byId(idString+int).getNumber() == ""  || sap.ui.getCore().byId(idString+int).getNumber() == null) {  sap.ui.getCore().byId(idString+int)  .setInfoState(sap.ui.core.ValueState.None);  } else {  sap.ui.getCore().byId(idString+int)  .setInfoState(sap.ui.core.ValueState.Success);  }  } else if (childValue && sap.ui.getCore().byId(idString) && parentValue != childValue && index == 0){  sap.ui.getCore().byId(idString).setNumber(childValue);  sap.ui.getCore().byId(idString).setNumberUnit(childValueUnit);  if (sap.ui.getCore().byId(idString).getNumber() == ""  || sap.ui.getCore().byId(idString).getNumber() == null) {  sap.ui.getCore().byId(idString)  .setInfoState(sap.ui.core.ValueState.None);  } else {  sap.ui.getCore().byId(idString)  .setInfoState(sap.ui.core.ValueState.Success);  }  }  }  }  }  }  },

Lastly, this code is tested and run successfully and I am sharing here for reuse.


Online and Offline capability in SAPUI5

0
0

Hi,

 

Here we comes to know how to store data into HTML5 local database. HTML5 introduced Local storage concepts. The Main use for this concept was offline capabilities and local persisted storage features, you can deliver the same rich user experiences online and offline that were previously available only in proprietary desktop application development frameworks.HTML5 localStorage is synchronous and is currently the only database storage mechanism that is supported cross-platform and cross-browser.

 

 

 

How to use?

 

Step1 :

 

SetItems to Local DB:

 

Window.localStorage.setItem(“giveKeyValues”, “YourArrayItems”);

 

For ex :

Var serNumArr = [];//Create Array put your rec into this array

var notiNumRcvdString =    JSON.stringify(serNumArr);

              window.localStorage.setItem("NewSerialNumbersMob26",notiNumRcvdString);

 

Capture.JPG

 

 

 

 

GetItems from DB:

 

 

Window.localStorage.getItem(“giveKeyValues”);




newScanArray = window.localStorage.getItem("NewSerialNumbersMob26"); // It will return your rec

 

var getSerNumInArray = new Array();

              getSerNumInArray  = JSON.parse(newScanArray);// Convert your Db rec to Below format

 

 

                     Internal function of JSON.parse(newScanArray):

 

                     getSerNumInArray [0] = 124567

 

getSerNumInArray [1] = 1245789 ...

 

 

 

Remove Items:

  Window.localStorage.removeItems(“giveKeyValues”);


It will remove Items based on your KeyValue




Thanks,

Karthik A

Create a running clock in UI5 Apps

0
0

In this example I am showing how to create a running clock sync with client machine's clock. This is very small example, but very useful to make application user friendly. No third-party js library is required. Just a small js will suffice this requirement. Here is the example:

In your application create a place to show clock, then in index.html you just write this function to set test in that place:

<script type="text/javascript">  function getCurrentTime() {  var Digital = new Date();  var hours = Digital.getHours();  var minutes = Digital.getMinutes();  var seconds = Digital.getSeconds();  var dn = "AM";  if (hours > 12) {  dn = "PM";  hours = hours - 12;  }  if (hours == 0)  hours = 12;  if (minutes <= 9)  minutes = "0" + minutes;  if (seconds <= 9)  seconds = "0" + seconds;  var sLocale = sap.ui.getCore().getConfiguration().getLanguage();  sLocale = "DE";  var time = Digital.toLocaleTimeString(sLocale);  var date = Digital.toLocaleDateString(sLocale);  if (sap.ui.getCore().byId("idMenuClock")) {  sap.ui.getCore().byId("idMenuClock").setText(time);  sap.ui.getCore().byId("idMenuClock").setInfo(date);  }  setTimeout("getCurrentTime()", 1000);  }  getCurrentTime();</script>

Here idMenuClock is the id of the button where I am showing time as text of that button and date as Info.

Give an error/warning sound to the user when an error occurs in Application

0
0

Here we go. It is a very helpful example for make user friendly application by using HTML5 audio tag. When an error occurs, users can be notified by a sound.


In index.html write this:

<body class="sapUiBody">  <div id="content"></div>  <audio id="idErrorSound">  <source src="audio/ErrorSound.mp3"></source>  </audio></body>

Now write a small javascript which can be called from your application when you found an error/mistake done from user end:

function playErrorSound() {  var audio = document.getElementById("idErrorSound");  audio.play();
}

Now here we can see a small code snippet where we are calling this js written above:

if (error) {        playErrorSound();        // open a dialog to give user a message        } 

Make a busy indicator while calling odata

0
0

In application, there are many instances where we are calling odata through ajax. Sometimes it takes time to process and give the output. To make the user aware of processing time, sometimes we see busy indicator in many applications. We can do the same in UI5 applications by writing this small javascript:


<script type="text/javascript">  function ajaxindicatorstart(text) {  if (jQuery('body').find('#resultLoading').attr('id') != 'resultLoading') {  jQuery('body')  .append(  '<div id="resultLoading" style="display:none"><div><img src="img/ajax-loader.gif"><div>'  + text  + '</div></div><div class="bg"></div></div>');  }  jQuery('#resultLoading').css({  'width' : '100%',  'height' : '100%',  'position' : 'fixed',  'z-index' : '10000000',  'top' : '0',  'left' : '0',  'right' : '0',  'bottom' : '0',  'margin' : 'auto'  });
jQuery('#resultLoading .bg').css({  'background' : '#000000',  'opacity' : '0.7',  'width' : '100%',  'height' : '100%',  'position' : 'absolute',  'top' : '0'  });
jQuery('#resultLoading>div:first').css({  'width' : '250px',  'height' : '75px',  'text-align' : 'center',  'position' : 'fixed',  'top' : '0',  'left' : '0',  'right' : '0',  'bottom' : '0',  'margin' : 'auto',  'font-size' : '16px',  'z-index' : '10',  'color' : '#ffffff'  });
jQuery('#resultLoading .bg').height('100%');  jQuery('#resultLoading').fadeIn(300);  jQuery('body').css('cursor', 'wait');  }
function ajaxindicatorstop() {  jQuery('#resultLoading .bg').height('100%');  jQuery('#resultLoading').fadeOut(300);  jQuery('body').css('cursor', 'default');  }
jQuery(document).ajaxStart(function() {  //show ajax indicator  ajaxindicatorstart('Processing.. please wait..');  }).ajaxStop(function() {  //hide ajax indicator  ajaxindicatorstop();  }); </script>

Write this function in index.html, then this global function will be automatically called while ajax start. You do not have to call this function explicitly. Sometimes you may not wish to give user busy indicator, then for that particular jQuery.ajax call you have to declare/avoid global setting false. Example:

jQuery.ajax({  url : url,  enableJsonpCallback: true,  jsonpCallback : 'getJSON',  contentType : "application/json",  dataType: "json",  async: false,  global: false,
success: function(data, textStatus, jqXHR) {
}});

Here we set global: false to stop busy indicator here.

How to create an Android PhoneGap plugin for UI5 Mobile

0
0

This post explains how we can create an Android PhoneGap plugin for SAPUI5 mobile app to achieve certain native functionality. Let’s say we have a user of SAPUI5 mobile app who travels across places to collect transaction data from different vendors where there is no proper network, so he/she wants to maintain the data locally in a device log file and when he connects to network the same transaction data should be read from the log file and uploaded to the server, this log file can be referred anytime offline or even could be shared with others as an attachment in mail.

SAPUI5 being a client side UI library doesn’t have access to create/maintain a file locally in the device. For the same reason we need to use hybrid web container framework PhoneGap. PhoneGap provides standard APIs for certain functionalities and Native Plugin development capability. By creating PhoneGap plugins we can interact in a more detailed manner with device features and functions that are not already exposed through the PhoneGap API.

The prerequisite for this post is the basic knowledge on Creating SAPUI5 Applications and fair idea on PhoneGap.

 

Step 1)Creating a SAPUI5 mobile Application

First create a simple SAPUI5 mobile application with just one input box and button on the UI to trigger the Plugin call (in our case this button will trigger the transaction in the app from UI5 side passing the value of amount entered in the input box and sends a method call to plugin for maintaining log, once the log is maintained in a local file by the plugin java code, it will return back the status to ui5).

DemoAppUI5.png

Step 2)Downloading Cordova

Download the latest version of Cordova from the Cordova site (preferably the zip format - cordova-3.4.0-src.zip), link below…

http://cordova.apache.org/

Extract the main folder (cordova-3.4.0) and then the subfolder (Cordova-android) and place the same in C:\ drive

 

Step 3)Creating the Android Cordova package

Open Command prompt and navigate to the below link

Cd C:\cordova-3.4.0\cordova-android\cordova-android\bin

Then give the command - create D:\PhoneGap\demoapp org.sample DemoApp and hit Enter, This will create a DemoApp with the package org.sample in the location D:\PhoneGap\demoapp

Cordova package.png

Inside the location D:\PhoneGap\demoapp you can find the folder CordovaLib\src copy the contents of this src to the main src folder D:\PhoneGap\demoapp\src

 

Step 4) Setting up the project in Eclipse

The following step requires the Eclipse installed with Android SDK and ADT plugins for the development of Android native app.

Open eclipse and import the DemoApp project (New->other->Android->Android project from existing code), exclude the CordovaLib sub project since we have already copied the contents of this src folder to the main DemoApp src folder.

Eclipse android project.png

Copy the contents from the SAPUI5 project created before to the Android project assests/www folder (index.html, views, and controllers)

DemoApp.png

Include a reference in the head tag of the document index.html to the Cordova and index JavaScript file.

 

<script type=”text/javascript” src=”cordova.js”></script><script type=”text/javascript” src=”js/index.js”></script>


Step 5) Creating a Plugin (JS)

Create a new JavaScript file in the assets/www directory called MyPlugin.js and place the following code at the top of the new file:

 

var MyPlugin = function(){};
MyPlugin.prototype.savelog = function(message, successCallback, errorCallback)
{
try{       
cordova.exec(successCallback,errorCallback,’MyPlugin’,’savelog’,message);
}
catch(e){}
};

Include a reference in the head tag of the document index.html to the newly created plugin JavaScript file.

 

<script type=”text/javascript” src=”MyPlugin.js”></script>

Below this, add a new script tag block, inside of which place the deviceready event listener and savelog method. The code to be added is given below.

 

<script type=”text/javascript”>        var onDeviceReady = function(){};        function savelog(amount)        {            var msg = window.plugins.MyPlugin.savelog(amount,                                    function(sMessage)                                     {                                    return sMessage;                                    },                                    function(eMessage)                                     {                                    return sMessage;                                    }                        );                        return msg;        }        function init()        {            document.addEventListener(“deviceready”,onDeviceReady,true);        }</script>

Call the init() function in the onLoad of body

 

<body onLoad=”init();” class=”sapUiBody” role=”application”>

Firstly, we define the class name for our JavaScript plugin, and then create the first method we will invoke called savelog.

Add the following code to the bottom of the file to load the MyPlugin class into the window.plugins object

 

if(!window.plugins) {            window.plugins = {};
}
if (!window.plugins.MyPlugin) {
window.plugins.MyPlugin = new MyPlugin();
}


Step 6) Creating a Plugin (Java)

Create a new Java class file in your project by accessing File|New|Class from the main Eclipse menu. You can also access the wizard by selecting File|New|Other from the main menu and finding the Java class option in the list, as shown in the following screenshot:

The New Java Class wizard will open to help you complete this task. Provide the reverse domain format package name, and set the class name to MyPlugin. As we want to hook into the Cordova framework, we will also make sure it extends the org.apache.cordova.CordovaPlugin class, which is part of the Cordova core API.

Click on the Finish button to complete the wizard. The new Java class file will now be open in your Eclipse editor window.  Let’s now add the native code for our plugin. We’ll begin by wrapping our code in a try/catch block to trap and handle any errors.

We’ll qualify the action value sent through to the plugin to ensure we have a valid method to run. In this case, we’ll check to make sure that it matches savelog. Path of the log file is maintained in the code as /sdcard/Apps/logs.txt,

The full code is given below.

 

package com.sample;
import org.apache.cordova.CordovaPlugin;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import org.json.JSONException;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.PluginResult;
public class MyPlugin extends CordovaPlugin {            @Override            public boolean execute(String action, String args, CallbackContext callbackContext) throws JSONException             {                        boolean stat = false;                        if (“savelog”.equals(action)) {                                     try {                                                File file = new File(“/sdcard/Apps/log.txt”);                                                boolean fileCreated;                                                if (file.exists()) {                                                            fileCreated = true;                                                }                                                else                                                {                                                            fileCreated = file.createNewFile();                                                }                                                if(fileCreated)                                                {                                                            PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(“/sdcard/Apps/log.txt”,true)));                                                            out.println(args);                                                            out.close();                                                }                                                else                                                {                                                            String result = “Internal Error”;                                                            PluginResult.Status status = PluginResult.Status.ERROR;                                                            PluginResult pluginResult = new PluginResult(status, result);                                                            callbackContext.error(result);                                                            stat = false;                                                            return false;                                                }                                                String result = “Transation saved”;                                                PluginResult.Status status = PluginResult.Status.OK;                                                PluginResult pluginResult = new PluginResult(status, result);                                                callbackContext.success();                                                stat = true;                                                return true;                                                                    } catch (Exception e) {                                                String result = e.getMessage();                                                PluginResult.Status status = PluginResult.Status.ERROR;                                                PluginResult pluginResult = new PluginResult(status, result);                                                callbackContext.error(result);                                                stat = false;                                                return false;                                    }                        }                        return stat;            }
}


Step 7) Mapping our plugin and Maintaining the uses permission

Before we can run the application, we need to add a mapping to our plugin within the Cordova config.xml file in the location res/xml/. Right-click on the file and select Open With Text Editor. Locate the plugins section and add a reference to our plugin within the following node:

 

<feature name=”MyPlugin”><param name=”android-package” value=”com.sample.MyPlugin” /></feature>

Also don’t forget to add the uses permission in the AndroidManifest.xml for creating and writing a file in the external storage and to access the SAPUI5 libraries.

 

<uses-permission android:name=”android.permission.INTERNET” /><uses-permission android:name=”android.permission.WRITE_EXTERNAL_STORAGE” />

Ideally for our use case the INTERNET permission is not applicable since the user mainly wants this functionality to work in remote parts by offline mode, for the same we also have to package the required SAPUI5 libraries in to the app resources instead of accessing the same from online, we will see about packaging the required UI5 library into the app in the following posts.

 

Step 8) Running our App

Let’s test our application and make sure we get a response from the plugin. Right-click on the main project folder and select Run as Android Application from the context menu to launch the application on the emulator. Here is the final output of the App running in mobile.

Final DemoApp.png

The complete project structure is as shown below

Complete project.png

 

How it works…

We created a JavaScript file to hold our client-side method calls and to handle success or error call-backs. We then created the native portion of the plugin, which extended the org.apache.cordova.CordovaPlugin class, thereby providing us with access and the ability to communicate between the JavaScript and native code.

Our JavaScript code called the cordova.exec method to invoke methods within our custom class:

 

cordova.exec( 
successCallback, 
errorCallback, 
'MyPlugin', 
'savelog', 
[message] 
); 

The exec () method accepts the following parameters:

Success: The success call-back function, which will run following a successful response from the plugin.

Error: The error call-back function, which will run following an unsuccessful operation and response from the plugin.

Service: This is mapped to the name of the native plugin class.

Action: The name of the action within the custom class to call and invoke.

Arguments: This is an optional parameter that allows you to send through data in an array, which can then be processed and used by the custom class.

The cordova.exec JavaScript method then invokes the execute function on the corresponding native plugin class.

The complete codes are given below.

 

Index.html

<!DOCTYPE html><html>    <head>        <meta charset=”utf-8” />        <meta name=”format-detection” content=”telephone=no” />        <meta name=”viewport” content=”user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi” />        <meta http-equiv=”X-UA-Compatible” content=”IE=edge”>                        <meta http-equiv=’Content-Type’ content=’text/html;charset=UTF-8’/>                        <script src=”https://sapui5.netweaver.ondemand.com/sdk/resources/sap-ui-core.js”                                                id=”sap-ui-bootstrap”                                                data-sap-ui-libs=”sap.m”                                                data-sap-ui-theme=”sap_bluecrystal”>                        </script>                        <script>                                sap.ui.localResources(“demoappui5”);                                 var app = new sap.m.App({initialPage:”idmainView1”});                                  var page = sap.ui.view({id:”idmainView1”, viewName:”demoappui5.mainView”, type:sap.ui.core.mvc.ViewType.XML});                                    app.addPage(page);                                    app.placeAt(“content”);                        </script>        <link rel=”stylesheet” type=”text/css” href=”css/index.css” />        <title>DemoApp</title>        <script type=”text/javascript” src=”cordova.js”></script>        <script type=”text/javascript” src=”js/index.js”></script>        <script type=”text/javascript” src=”MyPlugin.js”></script>        <script type=”text/javascript”>        var onDeviceReady = function(){};        function savelog(amount)        {            var msg = window.plugins.MyPlugin.savelog(amount,                                    function(sMessage)                                     {                                    return sMessage;                                    },                                    function(eMessage)                                     {                                    return sMessage;                                    }                        );                                    return msg;        }        function init()        {            document.addEventListener(“deviceready”,onDeviceReady,true);        }        </script>        <script>                   sap.ui.localResources(“demoappui5”);                   var app = new sap.m.App({initialPage:”idmainView1”});                    var page = sap.ui.view({id:”idmainView1”, viewName:”demoappui5.mainView”, type:sap.ui.core.mvc.ViewType.XML});                                                app.addPage(page);                                                app.placeAt(“content”);                        </script>    </head>    <body onLoad=”init();” class=”sapUiBody” role=”application”>        <div id=”content”></div>    </body></html> 


mainView.view.xml

<core:View xmlns:core=”sap.ui.core” xmlns:mvc=”sap.ui.core.mvc” xmlns=”sap.m”                        controllerName=”demoappui5.mainView” xmlns:html=”http://www.w3.org/1999/xhtml”>            <Page title=”DemoApp”>                        <content>                                    <Input id=”amount” type=”Text”></Input>                                    <Button press=”logHandler” text=”Save Offline (plugin call)”/>                                    <Button press=”sync” text=”Sync Data”/>                        </content>            </Page></core:View>


mainView.controller.js

sap.ui.controller(“demoappui5.mainView”, {            logHandler: function(){                        var amt = this.oView.byId(“amount”).mProperties.value;                        //do your functionality here                        var status = savelog(amt);                        this.oView.byId(“amount”).mProperties.value = “”;                        if(status == “OK”)                        {                                    sap.m.MessageToast.show(“Transaction log saved”);                        }                        else                        {                                    sap.m.MessageToast.show(“Transaction log failed; ” + status);                        }            }
});

 

I hope this post would be helpful to you all, feel free to comment for any queries. Thank you.

 

Kishore Kumar

Technology Consultant

Exa AG

Viewing all 789 articles
Browse latest View live




Latest Images