Skip to Content

During UI5con 2018 at St. Leon-Rot, Emanuele Ricci and I provided a hands-on session on how to get started with UI5 Custom controls. For this hands-on, we’ve prepared a tutorial to create a UI5 Custom control based on a 3rd-party JS library Lightbox2. This tutorials guides you through the following steps:

  • Configure the Web IDE for control development
  • Create the control
  • Use a 3rd-party JS library for your control
  • Wrap it in a Library
  • Consume the library

We share this tutorial in this blog in case you want to try this yourself, good luck!

You can find the slides of our session online: https://www.slideshare.net/secret/dAQIdAEsib1buK

Configure your SAP Web IDE

Open Google Chrome  
Navigate to https://account.hanatrial.ondemand.com/cockpit  
Go to the Neo environment (can be trial)  
Open Connectivity and select Destinations  
Create a new Destination  

Configure the destination to load the UI5 library template in the SAP Web IDE

(You can choose your own name)

Name=UI5LabFeature

URL=https://ui5librarytemplate-a6ac3f497.dispatcher.hana.ondemand.com

ProxyType=Internet

Type=HTTP

WebIDEEnabled=true

Authentication=NoAuthentication

WebIDEUsage=feature

Description=UI5Lab Feature

Create a second destination for the Library Manager

Name=librarymanager

URL=https://sapwebidelibrarymanager-a6ac3f497.dispatcher.hana.ondemand.com

ProxyType=Internet

Type=HTTP

WebIDEEnabled=true

Authentication=NoAuthentication

WebIDEUsage=feature

Description=Library Manager

Let’s go to the SAP Web IDE
Go to Services  
Search for “SAP Web IDE” and open de “Full-Stack” version  
Open settings and select “Features”  
Enable the feature “ui5labfeature”. This feature contains the template for the UI5 library. (You created a destination for this feature a few steps back)  
Also enable the “Library Manager”. This one should be in the feature list by default.  
Don’t forget to click on “Save” in the left bottom corner.  
And refresh your browser.  

 

Generate your library

Go to “File” -> “New” -> “Project from Template”  
Select the template “UI5Lab Library” in the category “UI5Lab”  
Give your library a name and namespace  
In the second step, give the name “Lightbox” for the first control and Finish the wizard  
The generated project will look like this  

Build and run your Library

Right click on your Library and select “Build”  
The build generates the dist folder with the library (including the preload) and two test folders. One for a local build and one that we need to use in the Web IDE  
In the Web IDE, use the test page in the folder “test-resources-webide”. Select the folder and click on Run  
This will show you a basic example of a UI5 control as part of the library. We can now start changing it.  

Include the lightbox library

Open the “Library Browser” on the right side of the SAP Web IDE, search for “lightbox2” and select the first line.  
Select download only excluding jquery and click on “+”  
It will raise an error but that’s okay.  

Images will not be downloaded due to CORS. Close the window.

It could be possible that not all files are saved correctly. Just to be sure, open all created files and save them.

 
Import the images from the zip file.  
Import the images in the folder lightbox2  
Just click “OK”.  
The folder structure will look like this with the library.  
Include the css file by adding this line in the library.source.less file in the base folder

@import (inline) “../../libs/lightbox2/css/lightbox.css”;

 

Create LightboxImage control

Create a new file for the control  
Call it “LightboxImage.js”  
Start by adding the skelet for the control
sap.ui.define(['sap/m/Image', './library'],
      function( Image, library) {
                "use strict";
                var LightboxImage = Image.extend("com.sap.ui5con.LightboxImage", {});
                return LightboxImage;
});

 

Add the metadata for the control with following properties
var LightboxImage = Image.extend("com.sap.ui5con.LightboxImage", {
                metadata: {                             library: "com.sap.ui5con",
                                properties: {
                                                /**
                                                 *            Src of the Image
                                                 */
                                                src: {
                                                                type: "string",
                                                                group: "Appearance",
                                                                defaultValue: null
                                                },
                                                /**
                                                 *            Thumb of the Image
                                                 */
                                                thumb: {
                                                                type: "string",
                                                                group: "Appearance",
                                                                defaultValue: null
                                                },
                                                /**
                                                 *            Height of the Image
                                                 */
                                                height: {
                                                                type: "string",
                                                                group: "Appearance",
                                                                defaultValue: "200px"
                                                },
                                                /**
                                                 *            Title of the Image
                                                 */
                                                title: {
                                                                type: "string",
                                                                group: "Appearance",
                                                                defaultValue: ""
                                                },
                                                /**
                                                 *            Alt attribute of the Image
                                                 */
                                                alt: {
                                                                type: "string",
                                                                group: "Appearance",
                                                                defaultValue: ""
                                                }
                                },
                                aggregations: {
                                                /**
                                                 *            Image aggregation for using the sap.m.Image control in this control (act as a Composite control)
                                                 */
                                                _image: {
                                                                type: "sap.m.Image",
                                                                multiple: false,
                                                                visibility: "hidden"
                                                }
                                },
                                events: {}
                }
});
Init function
init: function() {
                this.setAggregation("_image", new Image({
                                width: "100%",
                                height: this.getHeight(),
                                alt: this.getAlt(),
                                src: this.getThumb() ? this.getThumb() : this.getSrc()
                }));
},
Setter functions
setSrc: function(sSrc) {
                this.setProperty("src", sSrc, true /*no re-rendering of whole lightbox image needed*/ );
                this.getAggregation("_image").setSrc(sSrc); // Note: this triggers re-rendering of Image!
},
setHeight: function(sHeight) {
                this.setProperty("height", sHeight, true /*no re-rendering of whole lightbox image needed*/ );
                this.getAggregation("_image").setHeight(sHeight); // Note: this triggers re-rendering of Image!
}
Create a new file for the rendering part of the control  
Call it “LightboxImageRenderer.js”  
Create the renderer function
sap.ui.define(['sap/ui/core/Renderer', 'sap/m/ImageRenderer'],
                function( Renderer, ImageRenderer) {
                "use strict";
          
                var LightboxImageRenderer = Renderer.extend(ImageRenderer);
                LightboxImageRenderer.render = function(oRm, oControl) {
                                oRm.write("<a");
                                oRm.writeControlData(oControl);
                                oRm.writeAttributeEscaped("href", oControl.getSrc());
                                oRm.writeAttribute("data-title", oControl.getTitle());
                                oRm.writeAttribute("data-lightbox", oControl.getParent().getGallery());
                                oRm.write(">");
                                oRm.renderControl(oControl.getAggregation("_image"));
                                oRm.write("</a>");
                };
                return LightboxImageRenderer;
}, /* bExport= */ true);
Add the control to the list of controls in the library.js file  

Create Lightbox control

The “Lightbox” control should already be in your project. It was generated by the Library template  
Define Grid and lightbox. Use Grid to extend from.  
Add the following properties in the metadata
gallery : {type : "string", group : "Appearance", defaultValue : null},
alwaysShowNavOnTouchDevices : {type : "boolean", group : "Appearance", defaultValue : false},
albumLabel : {type : "string", group : "Appearance", defaultValue : "Image %1 of %2"},
disableScrolling : {type : "boolean", group : "Appearance", defaultValue : false},
fadeDuration : {type : "int", group : "Appearance", defaultValue : 600},
fitImagesInViewport : {type : "boolean", group : "Appearance", defaultValue : true},
imageFadeDuration : {type : "int", group : "Appearance", defaultValue : 600},
maxWidth : {type : "int", group : "Appearance", defaultValue : null},
maxHeight : {type : "int", group : "Appearance", defaultValue : null},
positionFromTop : {type : "int", group : "Appearance", defaultValue : 50},
resizeDuration : {type : "int", group : "Appearance", defaultValue : 700},
showImageNumberLabel : {type : "boolean", group : "Appearance", defaultValue : true},
wrapAround : {type : "boolean", group : "Appearance", defaultValue : false}
Register the id of the control in the init function
init: function() {
                //            Init all the things!
                if (!this.getGallery()) {
                                this.setGallery(this.getId());
                }
},
Configure the lightbox with the properties of the control in the “onAfterRendering” function
onAfterRendering: function() {

var config = {
alwaysShowNavOnTouchDevices: this.getAlwaysShowNavOnTouchDevices(),
albumLabel: this.getAlbumLabel(),
disableScrolling: this.getDisableScrolling(),
fadeDuration: this.getFadeDuration(),
fitImagesInViewport: this.getFitImagesInViewport(),
imageFadeDuration: this.getImageFadeDuration(),
positionFromTop: this.getPositionFromTop(),
resizeDuration: this.getResizeDuration(),
showImageNumberLabel: this.getShowImageNumberLabel(),
wrapAround: this.getWrapAround()
};

if (this.getMaxWidth()) {
config.maxWidth = this.getMaxWidth();
}

if (this.getMaxHeight()) {
config.maxHeight = this.getMaxHeight();
}

lightbox.option(config);
},
Delete the function setProp1
Create an exit function that will call the exit function of the Grid control
exit:function(){
Grid.prototype.exit.apply(this, arguments);
}
Go to the renderer file and change the code with this
sap.ui.define([ 'sap/ui/layout/GridRenderer'],
function( GridRenderer) {
"use strict";

var LightboxRenderer = {};

LightboxRenderer.render = function(oRm, oControl) {
GridRenderer.render.call("", oRm, oControl);
};

return LightboxRenderer;
}, /* bExport= */ true);

 

Update sample in library

Open the “LightboxSample.html” in the sample folder  
Change the test code to the following  
sap.ui.getCore().attachInit(function () {
var oLightbox = new com.sap.ui5con.Lightbox({
gallery:"lightbox-gallery",
alwaysShowNavOnTouchDevices:false,
albumLabel:"UI5 image %1 of %2",
disableScrolling:false,
fadeDuration:600,
fitImagesInViewport:true,
imageFadeDuration:600,
positionFromTop:50,
resizeDuration:700,
showImageNumberLabel:true,
wrapAround:false,
content:[
new com.sap.ui5con.LightboxImage({src:"https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/orange-tree.jpg", title:"Title 1", alt:"Alt 1"}),
new com.sap.ui5con.LightboxImage({src:"https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/submerged.jpg", title:"Title 2", alt:"Alt 2"})
]
});
oLightbox.placeAt("content");
});
Build and run your library again  
Click on an image and the lightbox will open  

 

Deploy to SAP Cloud Platform

Right click on the Library -> Deploy -> Deploy to SAP Cloud Platform  
Try to remember the Application name (we’ll need it later) and click on Deploy  
Done! Just close this popup.  

 

Consume the Library

Create a new UI5 app based on the template SAPUI5 Application  
Fill in a project name and namespace that you like  
Give the first view a name  
Open the neo-app.json and configure the path for your library

{
"path": "/resources/com/sap/ui5con",
"target": {
"type": "application",
"name": "myui5library",
"entryPath": "/resources/com/sap/ui5con"
},
"description": "UI5Lab Space Library"
},
Open the manifest.json and add a dependency to your library. You can use the descriptor editor or the code editor.

 

Go to the view, define the prefix for your library and add the Lightbox control between the content tags

<ui5con:Lightbox
gallery="lightbox-gallery"
alwaysShowNavOnTouchDevices="false"
albumLabel="UI5 image %1 of %2"
disableScrolling="false"
fadeDuration="600"
fitImagesInViewport="true"
imageFadeDuration="600"
positionFromTop="50"
resizeDuration="700"
showImageNumberLabel="true"
wrapAround="false">
<ui5con:LightboxImage
src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/orange-tree.jpg"
title="Title 1"
alt="Alt 1"/>
<ui5con:LightboxImage
src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/82/submerged.jpg"
title="Title 2"
alt="Alt 2"/>
</ui5con:Lightbox>
Run the app!  

 

To report this post you need to login first.

6 Comments

You must be Logged on to comment or reply to a post.

  1. Bilen Cekic

    great blog thanks!

    Light box is good but to be honest, SAPUi5 really need some proper controls. They need proper grid controls, charts and tiles even with the latest library. Somehow they really cannot follow up the modern web trends. I don’t understant the reason to implement a sap.ui.table control for huge records but not thinking to implement a basic copy paste functionality. Vizframe chart is another mess, i used a couple of times but never never again.  I won’t even suggest to my worst enemy. I am very happy with C3,ChartJS and ECharts. SAPUI5 tiles are another issues with their flat design and limited functionality. I endded up using bootstrap templates for better Card/Tile design.

    At the end, when i look my application, full of custom controls, dynamically generated HTML codes inside the controller and so on. I don’t want to talk performance for now :/

     

    (1) 
    1. Emanuele Ricci

      Bilen Cekic open source is here to help. SAPUI5 core developers have limited resources and they need to keep going with their roadmap.

      In the other end, they have a growing community and you can see all the progress we’ve made with the UI5Lab project 😉

      Do you prefer ChartJS over VizChart? You can grab my openui5-chartjs implementation 😉

      (4) 
      1. Bilen Cekic

        Yes understood, i don’t think also they have such concerns. Since their target contains mainly sap gui or webdynpro users, everything will look nice to them.
        Thanks for the github link 🙂 i implemented similar one but yours includes click event as well much more advanced.

         

        (1) 
  2. Bastian Wißler

    Hi Wouter,

    great blog about your library template!

    I tried to deploy a test application consuming the library on the SAPUI5 repository but there is an error message complaining about a wrong component extend (possibly it is not considered as library by the Netweaver system):

    “In application YCA_TEST_LIB used SAPUI5 library/ component com.test.lib not available. […]” (translated from German).

     

    Do we have to change something in some files or on the on-premise system to support these libraries?

    Thanks and regards Bastian.

     

    (0) 
  3. Ekansh Saxena

    Hello Wouter,

    Thanks for blogging about ‘not so obvious’ things in UI5 🙂

    When I am trying to follow along the blog, I am not able to find ‘Library Manager’ feature in my features list. I am on Neo Trial account.

     

    (0) 
    1. Ekansh Saxena

      Should have googled before posting the comment here 🙂

      I found that I have to create another destination to see Library Manger feature in web ide. I found the details in ‘How to get it’ section of your another blog here 

      Can you please update this blog to include this step as well?

       

      Thanks,

      Ekansh

      (1) 

Leave a Reply