Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 

Introduction, or why we are doing it

This post is written by ABAP developers for the ABAP developers facing the need or just a curiosity to develop new UI5 applications. The UI5 is a combination of various languages and frameworks like CSS3, jQuery, LESS, etc - just to name a few of them. However, the most of your time you will be developing in JavaScript, therefore knowing its basics is crucial for the beginners. As every programmer coming from the other platform tries first to find analogies to the known paradigms and programming styles, the same happen to us the ABAP developers. Even if later you will learn the beauty of JavaScript, all you need in the beginning is a survival kit making you able to create at least something which works correctly and keeps your productivity at a reasonable degree. The samples below are not exhaustive, we tried to keep them rather short, and we did not demonstrate nor discuss any further alternatives which exist. This blog is thought as a crash course and a quick reference guide to start develop immediately, sometimes by copying and pasting the sample code below.

Installed components

We used the following tools to develop and test our examples: Eclipse Juno (JEE bundle) with UI5 v1.10 plugin installed (you will need the UI5 plugin for the very last part where we will be looking at the techniques of calling the UI5 controls). We used another Eclipse plugin Jetty, and the current version of the Chrome Browser which turned out to be quite convenient for our tests.

How we develop and test

We created in Eclipse an UI5 Application Project without an initial view and placed all our JavaScript code into the <script> section of the index.html file. The results of our tests we displayed in the console which you can activate in the Chrome by pressing F12.

  • Use console.log() to trace and debug
  • Most of the browsers use F12 to activate/deactivate the console window
console.log('Function XYZ is called’);
console.log('Any type of data (fields, arrays, objects) can be logged’, vDate,
                     aArray, oModel);

JavaScript Samples

First, we activated the Strict ECMA Script 5 mode.  You should do it in the beginning of each <script> block.

"use strict";

The next thing you should take care of is minimizing of the global variables. For that, you basically should do two things – define one global object and put all your application into that object, and always declare variables using “var”.

In a UI5 project the first requirement will be pretty much always satisfied, as you will be developing within the set of predefined functions. The “var” best practice tells us always to put the declarations before the executable function code.

Creating functions

JavaScript functions are objects. This is why you can declare and assign them to a variable. You can create a function object by means of the following function expression:

var f = function () {
    console.log('variable f is a function');
};
f();

Chrome console:

Self-executing functions

There is a number of use cases when you need a function which executes once and disappears. These are, for example, the initialization functions. Note, in the following example there is no explicit function invocation. This sort of functions is executed immediately and does not leave any footprint when finished.

(function () {
    console.log('this is a self-executing function');
})();

Chrome console:

Creating Objects

As to the JavaScript objects, the following four object declarations appear to be useful:

  1. Gradual declaration of an object instance

Here we start with an empty declaration, then add two new properties and one function. Note, the declarations of properties “id”, “descr”, and the function “getDescr” have no “var”.  The object we created is a direct object instance, i.e. we cannot create any new instances of this type. Objects created this way have no constructors.

var oTurbine = {};
oTurbine.id = '4711'; // simple field
oTurbine.descr = 'Turbine';
oTurbine.getDescr = function () {
     return this.descr;
}
console.log('Object oTurbine -', oTurbine);
console.log('Object function getDescr() -', oTurbine.getDescr());

Chrome console:

  1. Short form of object instance creation

This form of object creation you will see quite often in UI5. Note colons between the names and the values and commas between the properties. Again, we cannot create any new instances of this object type. Objects created this way have no constructors.

var oScrew = {
     id: '4712',
     descr: 'Screw',
     getDescr: function () {
          return this.descr;
     }
}
console.log('Object oScrew -', oScrew);
console.log('Object function getDescr() -', oScrew.getDescr());

Chrome console:   

  1. Create objects using Constructor

The declaration of a function does not create an object instance. This is the constructor function which must be called with “new” to create a new object instance. Note, that the constructor name starts with a capital letter. Important to know that functions defined directly within the constructor will be copied to each object instance and thus unnecessarily consume memory. You should always use prototype functions (see next example) instead of functions definition within the constructor.

var Material = function (id, descr) {
     this.id = id;
     this.descr = descr;
};
var oLaptop = new Material('Laptop', '4713');
console.log( 'New object instance -', oLaptop );

Chrome console:   

  1. Define object methods as prototype

Instead of defining the methods directly in the constructor function, you should define all methods within the object prototype. This will optimize the memory consumption.

var MaterialModified = function (id, descr) {
     this.id = id;
     this.descr = descr;
};
MaterialModified.prototype.getDescr = function () {
     return this.descr;
};
var oLaptopMod = new MaterialModified('Laptop', '4713');

console.log('Object instance with new prototype method -', oLaptopMod);
console.log('Object methods must be defined as prototypes -', oLaptopMod.getDescr());

Chrome console:   

Now we will try to use our knowledge of the JavaScript objects for representing frequently used ABAP constructs like structures and internal tables.

Creating Structures

For a structure we will create another sub-object and define its properties.

var oBuildingBlock = new Material('BuildingBolck', '4714');
oBuildingBlock.oMeasure = {      // this is our “structure” representation
    unitCode: 'KGM',
    quantity: 100
};

console.log( 'Structured data -', oBuildingBlock.oMeasure.unitCode,
                                                   oBuildingBlock.oMeasure.quantity);
console.log( 'Display object -', oBuildingBlock);

Chrome console:

Working with arrays

When we, ABAP developers, want to utilize the concept of internal tables in JavaScript, the arrays may come at the closest in terms of provided functionality. In the next we list the major issues which an (ABAP) developer needs to know about arrays.

  1. Array index starts with 0
  2. Array elements can be of any type, mix is allowed
  3. Use push() to append a new element(s) to the end of array
  4. Use unshift() to insert a new element(s) to the beginning of array (not supported by IE8)
  5. Use splice() to delete an element(s) from array
  6. Arrays can have functions
  7. Further array operations can be found here
var aMaterialTable = [oTurbine, oScrew, oLaptop];
aMaterialTable.push(oBuildingBlock);      // append new element to the end
aMaterialTable.splice(2, 1);           // delete one element with index 2
console.log('Display array - ', aMaterialTable);
console.log('Arrays start with index 0 - ', aMaterialTable[0]);

aMaterialTable.func = function () {
console.log('Functions in arrays are possible - ', this[0]);
};

Chrome console:

Working with JSON

JSON is a format for serialization of JavaScript data (objects, arrays, etc). It has the same syntax as described in the “Short form of object instance creation”. You will come across JSON when working with the SAP NetWeaver Gateway services, creating your test data, etc. Usual operations on JSON are parsing and serialization. Next example demonstrates how to create a JSON string and parse it into the object.

var jStr = '{ "id": "4715", "descr": "Wristwatch" }';

var oJSON = JSON.parse(jStr); 
// var oJSON = jQuery.parseJSON(jStr); // alternative way of parsing
console.log( 'parse JSON to object - ', oJSON );

Chrome console:  

To render an array (or any other object) to JSON you can use the stringify() function.

var jStrFromArr = JSON.stringify(aMaterialTable);
console.log('Render an array to JSON - ', jStrFromArr);

var jStrFromObj = JSON.stringify(oLaptop);
console.log('Render an object to JSON - ', jStrFromObj);

Chrome console:  

Note, JSON can only carry properties (names and values), not the functions.

JSON Date Conversion

One common problem with JSON is the conversion of the dates. In JSON the dateTime data type is represented as an integer, like the following. JSON DateTime: /Date(1224043200000)/ To convert it into a readable format, you can use the following code.

//convert JSON date to Date object
var jStrDate = '/Date(1367043200000)/';
var oDateConverted = new Date(parseInt(jStrDate.substr(6)));
console.log('Date conversion - ', oDateConverted.toDateString());

Chrome console:

Exception handling

Application exceptions appear to be rarely used in JavaScript. However, as it is quite a good thing in ABAP, here’s an example for the exception handling in JavaScript.

MaterialModified.prototype.raiseLockErr = function () {
          throw Error("Material is locked: " + this.id + this.descr);
}

To catch an exception you can use the following code.

try {
     oLaptopMod.raiseLockErr();
} catch (e) {
     console.log( 'Error object -', e );
     console.log( 'Error message -', e.message );
}

Chrome console:

SAP UI5 controls

A UI5 control is created by calling its constructor. Here’s an example of a Button object.

var oSubmit = new sap.ui.commons.Button("main.btnSubmit", {
        text: "Submit"
     });
oSubmit.placeAt("content");

The signature of all constructors has a unified form (sId and mSettings). Note the keyword “new”.   

The API documentation describes also the single components of the parameters. Here’s an example of the constructor details for the Button control.   

The first parameter, the sId, is a unique identifier, which is very practical to set (e.g., you will need it for the input fields to retrieve the entered values). In the example above, the sID has a view name concatenated with the control name - “main.btnSubmit”. If you don’t define the sID yourself, it will be generated by the framework.  The second parameter mSettings is an object which contains properties, aggregations, associations, and events. It is usually created using the technique described in the section “Short form of object instance creation“. In our example the mSettings object looks like

{ text: "Submit" } 

Working with aggregations

From our experience the most challenging part of the control’s parameters is defining the aggregations. Let’s take a UI5 control that has an aggregation defined, e.g. the ListBox control. Here’s the constructor details of a Listbox control with an aggregation “items”.   

In the following example we define a JSON object and store it in a JSON model object. This model will be loaded into the Listbox control by calling the setModel() method. The Listbox control has an aggregation “items” which we bind to the array “/d/results”. The template property is repeatingly called for each element in the array, this is why we create a new object ListItem for each line in the array, and within this line we assign the array’s property “city” to the ListItem’s property “text”.

var oJSON = { "d":{
            "results":[{"city":"Berlin"},
                       {"city":"Hamburg"},
                       {"city":"Muenchen"},
                       {"city":"Ratingen"}]
                }
                      };

var oModel = new sap.ui.model.json.JSONModel();
oModel.setData(oJSON);  

var oListbox = new sap.ui.commons.ListBox("main.lstCity", {
                "items": {
                     path: "/d/results",
                     template: new sap.ui.core.ListItem().bindProperty("text", "city")
                     }
                    });
oListbox.setModel(oModel);
oListbox.placeAt("content");

The same Listbox control without databinding can look as follows.

var oListbox2 = new sap.ui.commons.ListBox("main.lstCity2", {
                items: [
                     new sap.ui.core.ListItem({text : "Bensheim"}),
                     new sap.ui.core.ListItem({text : "Freiberg"}),
                     new sap.ui.core.ListItem({text : "St.Leon-Rot"}),
                     new sap.ui.core.ListItem({text : "Walldorf"}),
                  ]
                });
oListbox2.placeAt("content");

The screenshot of the UI controls which we built in the above steps is provided below.

Postscriptum

All code samples can be tested within an Eclipse project. Run it in Eclipse as a Web application (we used the Jetty http server plugin for that) and copy the URL into the Chrome Browser. Keep the Jetty window open, and refresh your browser window (F5) to re-run the application. To see the console output, use F12 in the browser to switch to the debugging mode.

Literature

SAP UI5: SAP Help [link]

JavaScript Patterns by Stoyan Stefanov, published by O’Reilly, 2010

JavaScript: The Good Parts by Douglas Crockford, published by O’Reilly, 2008

About the authors

Vladislav Bezrukov is Development Architect at SAP Consulting focusing on integration technologies, Web and REST Services in ABAP NetWeaver platform (ABAP WS, Gateway). His further professional interests extend to SAP UI5 and HANA technologies, which he is using in his projects in the past couple of years. Email: vladislav.bezrukov@sap.com 

Florian Backfisch is Development Consultant at SAP Consulting. His professional interests are ABAP and UI technologies. Email: florian.backfisch@sap.com 

Johannes Demund is Development Consultant at SAP Consulting. He focuses on ABAP technologies and user interfaces, including NetWeaver Business Client, WebDynpro ABAP, and SAP UI5. Email: johannes.demund@sap.com

Disclaimer

This blog does not represent nor substitute the official SAP documentation. The views expressed by the authors do not necessarily reflect the views of their employer.

2 Comments