Skip to Content
Author's profile photo Wouter Lemaire

How to include third party libraries / modules in SAPUI5

Hi all,

 

In the JavaScript there already exists many libraries with a lot out of the box functionalities that make the developments easier. When working on complex SAPUI5 apps, you’ll probably use at least one third party JavaScript library. Two libraries that I often use:

In this blog I’ll explain how you can use these libraries in your SAPUI5 app. I’ll use the library MomentJs to show you how.

First go to the website of Moment.js: https://momentjs.com/

Click on: “moment-with-locales.min.js”

Copy the content of the page.

In your UI5 project create a folder “libs”. This is the place to put in all the third party libraries.

In the folder “libs” we create a file “moment.js”

In this file we paste the code that we’ve copied from the MomentJS website.

The project structure will look like this.

One of the ways to include this library into your project could be including the library in the index.html page. Please, don’t do this, this will not work when your UI5 app is used in the Fiori Launchpad. The Fiori Launchpad will start your app from the Component.js and not from the Index.html .

We have to include the library in the JavaScript files where we want to use it, in this example we’ll use it in the controller. You include the library by using the define functionality. In the define function you add the path to the file that contains the code of the library, in this case it will be “SAPUI5ExternalLibs/libs/moment” ( “<Namespace of the project>/<Path to the folder where it’s located>/<Name of the file>” ).

The value in the define function will be undefined and should be different from the global name of the library. Therefore we used the name “momentjs”. The global name of the library is “moment” in this case so we cannot use that.

You can read more details about this in the API Refrence

https://sapui5.hana.ondemand.com/#docs/api/symbols/sap.ui.html#.define

Third Party Modules
Although third party modules don’t use UI5 APIs, they still can be listed as dependencies in a sap.ui.define call. They will be requested and executed like UI5 modules, but their module value will be undefined.If the currently defined module needs to access the module value of such a third party module, it can access the value via its global name (if the module supports such a usage).Note that UI5 temporarily deactivates an existing AMD loader while it executes third party modules known to support AMD. This sounds contradictarily at a first glance as UI5 wants to support AMD, but for now it is necessary to fully support UI5 apps that rely on global names for such modules. 

 

After that we can use moment in our controller by using the global name of the library. In this example I use moment to add 18 days to today and get the name of that day in English, French and Dutch.

As you can see, the SAPWebIDE still gives errors when using the library although we’ve included correctly! To fix this errors we have to add the following line at the top of the controller:

/* global moment:true */

Where “moment” is the name of the global library. For lodash it would look like this:

/* global _:true */

“_” is the global name for the lodash library.

This will fix the errors!

In the view we just bind some text fields to the JSONModel

And this will give the following result.

A basic example to show you how to include libraries in your SAPUI5 project in the SAPWebIDE without having errors!

Additional note/question:

 

In the SAPWebIDE innovation version there is grunt integration for running JavaScript tasks. It would be great to also have a package manager like bower or like the NPM integration for Cordova plugins in Mobile apps.

 

 

Kind regards,

Wouter

Assigned tags

      37 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Mark Teichmann
      Mark Teichmann

      Hi Wouter,

       

      how does this compare to using the manifest.json to add external libraries to your project (as seen in the answer here: http://stackoverflow.com/questions/28016642/adding-a-custom-library-as-a-dependency-in-sap-fiori ) ?

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Hi Mark,

       

      In the stackoverflow topic I think they are talking about SAPUI5 libraries. In this blog I'm talking about non SAPUI5 JavaScript libraries. When you add the libary as a SAPUI5 library it wil search for a library.js file. The non-SAPUI5 JavaScript libraries don't have those files.

       

      Hope it helps.

       

      Kind regards,

      Wouter

      Author's profile photo Mark Teichmann
      Mark Teichmann

      I was also talking about external js libraries. I think you can include them by using the resources in manifest.json.

      Then the library is loaded automatically by the require mechanism ( according to help documentation)

      Author's profile photo Srikanth KV
      Srikanth KV

      Hi Wouter,

      As mentioned by Mark, I have used third party libraries like "underscore.js" in projects and linked that as resources in manifest.json file. With this I can access "underscore" global name "_" in all the controllers without the need for injecting library again using AMD in each controller....

      can you let me know the difference between manifest.json resources and your approach?

       

      Regards

      Srikanth

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      The difference between the manifest and my approach:

      • using the manifest will load the library at the start of the UI5 app
      • my approach will load the library only when it's defined, but only once. If it's already loaded, it will not load again.

       

      Kind regards,

      Wouter

      Author's profile photo Srikanth KV
      Srikanth KV

      Thanks Wouter for the info..

      Author's profile photo Ankur Babu
      Ankur Babu

      Hi Srikanth KV

      Could you please tell me how are you using it? Are you adding the min.js code of library locally in the project or using directly with the url in manifest.json. I am not able to use with the url, similar to example mentioned below

      	"sap.ui5": {
      		"resources": {
      			"js": [{
      				"uri": "https://cdn.xxx.com/xxx/xxx.4.19.20.min.js",
      				"name": "xxx.4.19.20.min.js",
      				"version": "4.19.20"
      			}]
      		},
      Author's profile photo Boghyon Hoffmann
      Boghyon Hoffmann

      Hi Wouter, Thank you for this great post. I'm using your approach to include C3.js in my project. I have some questions though:

      1. Besides the script file, C3 also needs its own c3.css file to be loaded. Any idea how to load CSS files on demand? Currently, I'm doing it in the app descriptor (sap.ui5/resources/css) but this loads the file right away at the start. I guess it's not a big deal since the CSS file is just 1 KB and gets loaded asynchronously together with other files. What do you think?
      2. The lib uses "c3" as a global variable name so I had to include
        /* global c3 */​

        in order to prevent the "error". Where can I find a documentation about the usage of such syntax? The API ref doesn't explain much.

      3. I noticed that Web IDE doesn't complain about the usage of global names from UI5's third party libs such as "d3" and "sinon". Do you know why? Or is the IDE making an exception for them?

      Thanks in advance!

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Some good questions.

      1. I don't think it's a problem, as you say it's only 1kb.
      2. I found it in an example of SAP but no docu...
      3. I guess they have exceptions for everything in the UI5 SDK.

      Kr,

      Wouter

      Author's profile photo Boghyon Hoffmann
      Boghyon Hoffmann

      I just realized the syntax for the global variables is from ESLint rather than from Web IDE. The documentation can be found here: https://eslint.org/docs/user-guide/configuring#specifying-globals which answers my last two questions.

      Author's profile photo Srikanth KV
      Srikanth KV

      Hi Wouter,

      I'm using HANA WebIDE for UI5 development and XSOData services for data retrieval.

      Tried using your approach for 'moment.js' and 'lodash', at runtime the libs are not loaded, but with the same code when executed on my local PC with IIS server it works fine.

      I think the issue here is not the approach of including the libraries but something else,Can you help me with this.

      Here is what I did so far:

      1. Downloaded 'moment.js' from https://momentjs.com/downloads/moment-with-locales.min.js
      2. Created 'libs' folder and included the downloaded file as 'moment.js'
      3. Included 'moment.js' through sap.ui.define AMD procedure
      4. Error
        Uncaught Error: Mismatched anonymous define() module: function (){"use strict";function a(){return re.apply(null,arguments)}function b(a){re=a}function c(a){return a instanceof Array||"[object ​

      Thanks in Advance

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Hi Srikanth,

       

      I didn't tried it in the HANA Web IDE yet. Which version are you using? Already the same SAP Web IDE as for Fiori apps or an older version? What version of SAPUI5 SDK are you using in the HANA Web IDE? What if you try to use the latest online sdk?

      Regards,

      Wouter

       

      Author's profile photo Srikanth KV
      Srikanth KV

      Hi Wouter,

      Sorry for the late reply. I have tried using CDN version of SAPUI5 SDK also and facing the same issue.

      Regards

      Srikanth

      Author's profile photo Anton Snitko
      Anton Snitko

      Can I just use

      jQuery.sap.require("SAPUI5ExternalLibs/libs/moment");
      then it will be available.
      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Will also work. But better to use the define function.

      Author's profile photo Naga Prakash
      Naga Prakash

      Hi ,

      I have used the same method to load the Ramda js and it got loaded, i can see the fiel in the Sources tab in chrome developers tool. But the global variable R is undefined what could be the reason ?

      Thanks,

      Naga

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      The name for the library should be different in the define function then the original name.

      Author's profile photo Former Member
      Former Member

      Hi Wouter,

       

      You define momentjs as an argument to the define function but in the controller you use the global moment() instead of momentjs(). Is there a reason for this? I would expect momentjs() to be the correct usage.

      I have tested this on my own and both usages work. In which case, why add the momentjs argument in the first place if it is not being used?

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      That's what I've read in the documentation. maybe this has been changed in the newer version.

       

      Author's profile photo Former Member
      Former Member

      Hi Wouter,

       

      Great post, I think I'm getting close but I'm getting the errors further below in Chrome. This is what I have in my controller:

      sap.ui.define([
      	"sap/ui/core/mvc/Controller",
      	"sap/ui/model/json/JSONModel",
      	"TestProject/lib/moment"
      
      ], function(Controller, JSONModel, momentjs) {
      	"use strict";
      	return Controller.extend("TestProject.controller.Main", {
      	    /* global moment:true */
      		onInit: function() {
      		    var day = moment().add(7, 'days');

       

      I've added moment.js to my "lib" folder and this is what I'm getting in the Chrome console:

      Any clues? I'm stumped, thanks in advance for your help.

      Jim

       

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      Could you share your project via plunker?

      Author's profile photo Former Member
      Former Member

      In your function declaration, you are injecting momentjs and then ur trying to access it as moment variable, I think that is your main issue. Change your momentjs to moment and then it should work

      Author's profile photo Andrés Nebel
      Andrés Nebel

      Did you fix it? we are getting errors of the like. All of the sudden, third party libraries aren't working anymore.

      Author's profile photo Shanir Tvaija
      Shanir Tvaija

      Hi.

      I have a additional requirement for leaflet drawing for constructor control to include this script into my FLP app.

      https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/0.4.2/leaflet.draw.js
      
      As I cannot use index.html, how should I include that into Component.js?
      Including it in manifest under resources "js" [{ "uri": "........"}] throws error.
      
      Thanks for help.
      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      This works for me:

      "resources": {
      			"js": [ {
      				"uri": "libs/lodashjs/lodash.min.js",
      				"name": "lodash.min.js",
      				"version": "4.17.5"
      			}],
      			"css": []
      		}

      Gr,

      Wouter

      Author's profile photo Boghyon Hoffmann
      Boghyon Hoffmann

      I just realized it’s not a good practice anyway to include JS files in sap.ui5/resources/js since those files will be loaded via sync XHRs (loadSyncXHR). I’m sure this will be fixed in later versions of UI5 but until then, it’s better to include the third-party libraries in sap.ui.define or .require in order to load them asynchronously.

      See also https://github.com/SAP/openui5/issues/3137.

      Author's profile photo Christian Späh
      Christian Späh

      Hi Wouter,

      thank you very much for your tutorial. I am able to import moment.js into my SAPUI5-app. With sap.ui.define in my controller or as js resource in manifest, both ways work fine when I run my app in SAP Web IDE. When I deploy my app to SAP CP and run it inside a Fiori Launchpad, it does not work. I am getting an error: "Uncaught ReferenceError: moment is not defined". I am wondering if I or FLP is doing something wrong. Can you confirm, that your code is still running in FLP?

      Best regards,

      Christian.

       

      Author's profile photo Wouter Lemaire
      Wouter Lemaire
      Blog Post Author

      For me both ways work in Fiori on premise... Not yet tried it in Cloud FLP.. You should raise a QA for that

      Author's profile photo Christian Späh
      Christian Späh

      Hi Wouter,

      thank you for your answer. I wrote a QA, for those who are interested.

      Best regards,

      Christian.

      Author's profile photo Christian Späh
      Christian Späh

      I got an answer from SAP-Support. There is some additional coding necessary, to load a library in Fiori Launchpads. I posted the code here.

      Author's profile photo Ali M. Qazi
      Ali M. Qazi

      Hi Wouter,

      I tried following steps mentioned in your blog but still i am unable to load the library. I am trying to use SAPUI6 World map library in my application. Please find the screenshot below and would appreciate if you can please help me with this

       

       

      Is there something that i am missing.

      Thanks alot for your help and support

      Regards

      Ali Q

      Author's profile photo Sascha Rissel
      Sascha Rissel

      Dear Wouter,

      we are currently starting UI5 development on Cloud Foundry for adding the applications to cFLP and are also trying to include 3rd party libs like MomentJS into our application.

      We followed your steps above, but unfortunately we get URL generated like

      https://sapui5.hana.ondemand.com/resources/<namespace><appName>/libs/moment.js

      which apparently don't fit, since they do not reference the library from our deployed application, but from hana.ondemand.com.

      We also tried to work with UI5's uiloader:

      sap.ui.loader.config({
      	shim: {
      		"namespace/appName/libs/moment": {
      			amd: true, // URI.js reacts on an AMD loader, this flag lets UI5 temp. disable such loaders
      			exports: "moment" // name of the global variable under which URI.js exports its module value
      		}
      	}
      });

      but apparently that doesn't seem to change anything.

      Did you for yourself already had the opportunity to try loading 3rd party libs on CF envirionment and maybe have some hints for us?

      Kind regards,
      Sascha.

      Author's profile photo Simon Perstorfer
      Simon Perstorfer

      Hi Sascha Rissel

      If you add the following code to the Compoment.js, for example Moment will be loaded via cdn.

      sap.ui.loader.config({
          paths: {
              "your/namespace/thirdparty/moment": "https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.24.0/moment-with-locales.min",
          },
          shim: {
              "your/namespace/thirdparty/moment": {
                  amd: true,
                  exports: "moment",
              },
          },
          async: true,
      });

      The definition of the shim ensures that the import is executed correctly in controllers using sap.ui.define and that the module (e.g. Moment) is contained in the variable of the import.

      sap.ui.define([
      		"sap/ui/core/mvc/Controller",
      		"your/namespace/thirdparty/moment"
      	], function(Controller, moment) {
      	"use strict";
      
      	return Controller.extend("com.sample.controller.ComboBox", {
      
      		onInit: function () {
                          moment();
      		}
      	});
      });

      Kind regards,
      Simon

       

      Author's profile photo Marco Beier
      Marco Beier

      Hi Simon,

      so far so good. Is there a possibility to include a third party library thats installed within node_modules (dep. via package.json)? I've read about 'Project Shims' but I couldn't quite make it work. Any Idea/Example or possible pointers to examples?

      Best Regards,

      Marco

      Author's profile photo Carsten Michels
      Carsten Michels

      Did you find a solution here? Is it possible to use thirdparty libraries through the package.json?

      Author's profile photo Eyüp Karaavci
      Eyüp Karaavci

      Hi all;

      Maybe you can try this one:

      onInit: function () {
              $.getScript("https://momentjs.com/downloads/moment.js");
      },

      Best regards.

      Eyüp.

      Author's profile photo Soheil Tehrani
      Soheil Tehrani

      Hi,

      I get this error!!!

      Error

      Error

      Here is my project structure:

      Project%20Structure

      Project Structure