Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
reiner_hille-doering
Active Contributor

There are several questions coming up frequently, both in our SDK workshops and here in the forum. Thus I thought it might be a good idea to blog about some typical problems that you as Design Studio developer could be running into.

The first thing I want to write about is the different ways how an SDK component could integrate resources, such as images, CSS files, fonts etc. Probably most components need such resources. Using the resources is just normal HTML and JavaScript, but first we need to differentiate two kinds of resources, depending who defines which file to use:

  • Static resources: Those come with the SDK component and are not intended to be modify by the user of the component. Typical examples are decorations of UI element, e.g. the icon shown on a button.
  • Dynamic resources: Those are defined by the user of a component, e.g. if your component allows the user to define a background image using the Design Studio Properties window.

Static Resources

The easiest way to include static resources is a CSS file. The SDK has the <cssInclude> tag where you can reference one or more CSS files that come with your SDK extension. As soon as at least one instance of your SDK component is contained in the app, the CSS file is automatically loaded into the page. How this works is shown in the ColoredBox example – making the box having a black border with rounded corners.

You may have seen that the round boarder is not shown when you drop the first ColoredBox into an empty application. Reason is the feature: The Design Studio runtime analyzes an app before the HTML is produced. It will include all needed JS and CSS files into the header. If the first ColoredBox is added into an empty app, the Runtime will dynamically load the new JS files. But it doesn’t load the new CSS files. Fortunately this issue has been resolved in Design Studio 1.3 SP1, thus with an up-to-date Design Studio you will see round corners from start.

As you can include CSS files, it is also easy to include pictures through CSS: If you e.g. want to modify the ColoredBox into a PictureBox, add a picture into the CSS folder or a subfolder. The reference it with a relative path from the CSS:


.coloredBox {

      border-radius:25px;

      border-width: 4px;

      border-color: black;

      border-style: solid;

      background-image: url("img/Desert.jpg");

       background-size: 100%;

}


To see it running, you also need to remove the “color” property getter/setter, as it would overwrite the background image with a background color.

If you want to select one of multiple static images, best use several CSS classes and modify the assigned class in your JS code.

You might ask: “Why not simply use an IMG element?” There are some good reasons to prefer a styled DIV over an IMG:

  • You have a lot of possibilities to control the appearance, sizing etc. of the picture using CSS3 attributes, e.g. background-repeat and background-size.
  • The users of your component can use custom CSS files to replace your images with their own.
  • The URL to your image is relative to the CSS. As Design Studio correctly calculates the URL of the CSS file on all platforms, the exact path the image isn’t something your need to care about.

The last point is somehow the “killer argument” to go with CSS whenever possible. Unfortunately there are situations where you must specify the exact URL of your image or other resource, e.g. in SVG image elements.

Fortunately there is a little trick to calculate the path of anything that comes with your SDK component: As you component.js is loaded into the page with a <script> element, at the moment of loading it is the last <script> tag on the page. This fact can be used to calculate the “src” path:


(function() {

var scriptSrc = $("script:last").attr("src");


sap.designstudio.sdk.Component.subclass("com.sap.sample.coloredbox.ColoredBox", function() {

       this.init = function() {

              var imageUrl = scriptSrc.replace("js/component.js", "css/img/Desert.jpg");

              var image = $("<img/>").width("100%").height("100%").attr("src", imageUrl);

              this.$().append(image);

       };

    });

})();


I have modified the handler to be encapsulated in a self-calling function to get a private variable scope. In the first line I use jQuery to get the “src” attribute of the last script element in a variable. This is later used to calculate the path to the image by replacing the relative path to component.js.

Dynamic Resources

Dynamic resources, e.g. images that the Design Studio user associates with their app, are even more dependent on the Design Studio platform.

In local mode, those resources reside inside of the folder of the app in the local repository. In BIP those resources are global BIP repository object, in NetWeaver there are stored as MIMEs in ABAP and on HANA they are again local repository objects.

Thus the exact URL is not known upfront. Therefore the SDK comes with the property type “Url” that automatically creates the correct URL depending on the platform. Unfortunately we can’t provide picker dialogs for those Url properties in the designer, as the platform handle different resource types quite differently.

Thus a good tip of user of an SDK component having Url properties on BIP or NetWeaver:

  1. Add an image component.
  2. Use the Image’s “Image” property picker to upload the image and fill the property correctly.
  3. Copy the property value to the SDK component’s URL property.

Now, what will you do if your SDK component wants to display may different images, e.g. depending on data?

Simply create a “template” Url property and fill it with a path pointing to the place where all the images are located. Then your code can replace the template name with the real name.

In our training class sample showing a Scatterplot chart with country maps we used this trick:

First we have the Url property “placeholderimage” with getter/setter:

this.placeholderimage = function(value) {

      if (value === undefined) {

             return _placeholderimage;

   } else {

           _placeholderimage = value;

            return this;

   }

};

Then we assign the SVG element the URL depending on Country of the data source cell – all using D3.


svgimgs.attr("xlink:href", function(d, index) {

     var dimValForPicture = getTextForDimension(index, _imagedim);

     var url = "";

     if (dimValForPicture && _placeholderimage) {

       url = _placeholderimage.replace("DEFAULT", dimValForPicture);

     }

     return url;

});


In current version of Design Studio, the template image should exist, even it it is not used. Else there will be ugly entries in the log file. In next Design Studio release this should be fixed, so you could make the template URL property hidden and assign a reasonable default value to it.


So far my first SDK blog. If you have any areas of interest, please let me know. I'll try to consider those proposals in my next blog.

13 Comments