Technical Articles
Learn JavaScript as ABAP developer Part 4
- Variable declaration
- Function declaration
- Concurrency with Promises and async functions
- Encapsulation with modules
- Scripting in UI5 applications
Encapsulation
Modules encapsulate functions and variables like a ABAP function group. They can be categorized in CommonJS modules and AMD modules. CommonJS modules are primary used by node.js application, whereas AMD modules are used by UI5. The API of these categories is a bit different.
CommonJS modules
CommonJS modules can be used for node.js applications or in most modern browsers.
Writing modules
A CommonJS module is written in one file. Every module has a object module.exports
. Every property attached to this object can be used later. Functions or variables, which are not attached as property to this object, are just visible inside the module.
The following module exports the functions setBirthday
and getBirthday
, whereas the function normalizeBirthday
is just visible inside the module.
let birthday;
function normalizeBirthday() {
birthday.setHours(0);
birthday.setMinutes(0);
birthday.setSeconds(0);
}
module.exports.setBirthday = date => {
birthday = new Date(date);
normalizeBirthday();
}
module.exports.getBirthday = () => {
return birthday;
}
Like variables in ABAP function groups variables inside of a module are cached throughout the execution process. Once the birthday is set in the function setBirthday
, the function getBirthday
returns this day in every invocation. When the process terminates, the cache is cleared.
Using modules
Modules can be imported with the require
function. The require function returns the module.exports
-object. Assuming the above module is declared inside a file birthday.js, it can be imported from another module in the same folder like this:
const birthday = require('./birthday');
birthday.setBirthday('2002-05-08');
The import
statement can be used instead. This statement allows the import of a property subset or the import of the whole module.
To import a subset (just the function setBirthday
):
import { setBirthday } from './birthday'.
To import the whole module:
import birthday from './birthday';
The prefix “./” refers to the location of the module-file. “./” means the current directory. If the module is located inside another folder, we add the relative posix-path. In node.js modules can come from other packages (like react or lodash) or can be local modules. Locale modules get always a path prefix, whereas modules from other packages don’t get any path prefix. Modules from other packages are always searched in the folder node_modules.
UI5 modules
UI5 has a own module loader, which uses the API of AMD modules.
Writing modules
Modules are defined with the sap.ui.define
function. If no module name is specified, the first argument of this function is an array with dependencies (other modules). The second argument is the so called factory function, which contains the logic of this module. The dependencies must be supplied in the correct order to this function. The following module uses the dependency sap/ui/model/odata/v2/ODataModel
to define an ODATA model object.
sap.ui.define(["sap/ui/model/odata/v2/ODataModel"], function(ODataModel){
"use strict";
return new ODataModel("/sap/opu/odata/sap/PP_MRP_COCKPIT_SRV");
});
It’s possible to add a unique module-name as first argument to the sap.ui.define
function, but it’s not recommended.
sap.ui.define("Quickstart/App/model", ["sap/ui/model/odata/v2/ODataModel"], function(ODataModel){ "use strict"; return new ODataModel("/sap/opu/odata/sap/PP_MRP_COCKPIT_SRV"); });
The dependencies and the factory function are then the second and the third argument.
Using modules
Like CommonJS modules UI5 modules are referred with a relative or a global resource path. The relative resource path is according to the current directory. Global modules are loaded from SAP’s registry. UI5 provides the function sap.ui.require
to directly access UI5 modules:
sap.ui.require([
"./model"
], function (ODataModel) {
"use strict";
console.log(ODataModel);
});
It’s possible to include a module as a dependency of another module. A UI5 controller can make use of the above model-module:
sap.ui.define([
"sap/ui/core/mvc/Controller",
"./model"
], function (Controller, ODataModel) {
"use strict";
return Controller.extend("Quickstart.App", {
onInit : function () {
this.getView().setModel(ODataModel);
},
onChange: function (oEvent) {
var bState = oEvent.getParameter("state");
this.byId("ready").setVisible(bState);
}
});
});
Thanks for this great blog series.