With the introduction of the function sap.ui.define
in the version 1.28, SAPUI5 has introduced the support for Asynchronous Module Definition (AMD).
- A module is a JavaScript file that can be loaded and executed in a browser.
- Asynchronous Module Definition (AMD) is a JavaScript API which specifies a way to define a module and its dependencies in such a way that they can be loaded asynchronously without worrying about the loading order.
In this blog, I’ll try to explain the syntax, usage and the behavior of the sap.ui.define
function with the help of the good old “Hello World” program. So let’s get going!
Prerequisites
Create an Application Project for SAPUI5
Open Eclipse and go to the menu option, File -> New -> Other…. In the New window, open the node SAPUI5 Application Development and select the option Application Project. Click on the Next button.
Provide a name to the project. Let’s call it sapui5.amd.demo. Select the library sap.m
and check the option Create an Initial View. Click on the Next button.
In the next window, provide a name to the view. Let’s call it main. Select the Development Paradigm as XML. This will create a view in XML. Click on the Finish button.
A project structure similar to the one shown below should be created
Modify index.html
Open the index.html
file and update it with the following code. The Bootstrap script section has been modified to prevent the early loading of sap.m
library. Also, the auto generated code which creates an instance of sap.m.App
has been commented out for similar reasons. A for-loop
prints out the initial list of loaded library modules when index.html
is run in a browser.
<!DOCTYPE HTML> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv='Content-Type' content='text/html;charset=UTF-8' /> <!-- Replace this with the modified bootstrap section below <script src="resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-libs="sap.m" data-sap-ui-theme="sap_bluecrystal"> </script> --> <!-- Do not load the sap.m library right now. We'll do it asynchronously in sap.ui.define --> <script src="resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-theme="sap_bluecrystal"> </script> <script> sap.ui.localResources("sapui5.amd.demo"); /* * Since we are not creating an instance of sap.m.App to * avoid the loading of sap.m at this stage, comment this out. */ /* var app = new sap.m.App({initialPage:"idmain1"}); var page = sap.ui.view({id:"idmain1", viewName:"sapui5.amd.demo.main", type:sap.ui.core.mvc.ViewType.XML}); app.addPage(page); app.placeAt("content"); */ // Get reference to the Core object var oCore = sap.ui.getCore(); // Place the XML view in the body of this page oCore.attachInit(function() { sap.ui.core.mvc.XMLView({ viewName : "sapui5.amd.demo.main", }).placeAt("content"); }); // Set the log level to INFO jQuery.sap.log.setLevel(jQuery.sap.log.Level.INFO); // Print out the list of all currently loaded libraries jQuery.sap.log.info("--- Loaded Libraries in INDEX.HTML ---"); var oLibMap = oCore.getLoadedLibraries(); for ( var key in oLibMap) { jQuery.sap.log.info("Library name", key); } </script> </head> <body class="sapUiBody" role="application"> <div id="content"></div> </body> </html>
Modify main.view.xml
Open the main.view.xml
file and update it with the following code. Its almost the same as the auto-generated code in Eclipse with just the title added to it.
<core:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="sapui5.amd.demo.main" xmlns:html="http://www.w3.org/1999/xhtml"> <Page title="Asynchronous Module Definition Demo"> <content> </content> </Page> </core:View>
Modify main.controller.js
The controller is where the AMD related action takes place. Open the main.controller.js
file and update it with the code given below. The important change here to note is in the first line where the function call sap.ui.controller()
has been commented out to make way for the AMD function sap.ui.define()
which has the following syntax: sap.ui.define(sModuleName?, aDependencies?, vFactory, bExport?)
sModuleName
is an optional parameter which is the name of the module being defined. If omitted, it will be replaced with the name that was used to request the module. So, If the name of a module say ‘LoginModule
‘ is not passed as a parameter, it can be requested as ‘sap/login/LoginMudule
‘ given that it is stored in a file ‘sap/login/LoginModule.js
‘aDependencies
is a string[ ] of module names which are a dependency. The dependency modules are loaded before the value of the currently defined module is determined.vFactory
is a mandatory factory function which calculates the value of the module. Each of the dependency module names are passed as a parameter to this factory function in the same order in which they are specified in the string[ ].bExport
is a boolean variable which is reserved for SAP’s use.
Detailed information about sap.ui.define()
can in found in the API Reference.
In the example below, no module name has been passed. And the dependency string[ ] contains the module names ["sap/ui/core/mvc/Controller", "sap/m/MessageToast"]
. These names are then passed as parameters (in the same order) to the factory function as function(Controller, MessageToast)
The code in onInit
lifecycle method of the controller prints out the list of all the loaded libraries. And finally the onAfterRendering
function displays a brief Hello World message on the screen using the sap.m.MessageToast.show()
//sap.ui.controller("sapui5.amd.demo.main", { sap.ui.define([ "sap/ui/core/mvc/Controller", "sap/m/MessageToast" ], function(Controller, MessageToast) { "use strict"; return Controller.extend("sapui5.amd.demo.main", { /** * 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 sapui5.amd.demo.main */ onInit: function() { // Get reference to the Core object var oCore = sap.ui.getCore(); // Print out the list of all currently loaded libraries jQuery.sap.log.info("--- Loaded Libraries in INIT of controller ---"); var oLibMap = oCore.getLoadedLibraries(); for (var key in oLibMap) { jQuery.sap.log.info("Library name", key); } }, /** * 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 sapui5.amd.demo.main */ // 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 sapui5.amd.demo.main */ onAfterRendering: function() { MessageToast.show("Hello World!"); }, /** * Called when the Controller is destroyed. Use this one to free resources and finalize activities. * @memberOf sapui5.amd.demo.main * */ // onExit: function() { // // } }); });
The “use strict”; literal expression was introduced by JavaScript 1.8.5 (ECMAScript 5). It tells the browser to execute the code in a so called “strict mode”. The strict mode helps to detect potential coding issues at an early state at development time, that means, for example, it makes sure that variables are declared before they are used. Thus, it helps to prevent common JavaScript pitfalls and it’s therefore a good practice to use strict mode.
Deploy and Run Application
Start your server and deploy the application. Open a new browser window (this example uses the Chrome browser) and open the Developer Tools.
Open the following URL in browser http://localhost:8180/sapui5.amd.demo/
Please use the port number according to your server configuration. Loading the index.html
displays the Hello World message briefly and will print out the logs in the Developer Tools console. You can see that the sap.m module
is not loaded until the module dependency list is passed to sap.ui.define
Hope this helps you understand sap.ui.define
better. See you in the next blog!