Skip to Content

This is part of a tutorial series on creating extension components for Design Studio.

In our last installment, we too our first baby steps with D3; drawing a colored arc with defined inner and outer radii. We did this in raw html and the next step here will be to bring this into Design Studio.  To do this, we’ll need to do two things:

  1. We’ll need to ensure that D3 is available to Design Studio’s component.
  2. We’ll need to copy our javascript from the html file to the component’s component.js file and adapt it for life within a component.

Starting with your component project open in Eclipse:

Step 2b.1 –

Our first challenge is with adding includes in Design Studio components.  We actually did this for our component.js file in Step 1.10f, when we set up our component.  The <jsInclude> element lets you define any Javascript file that is going to be imported and can be an internet URL, or a local filepath.  Now we could import D3 this way and grab it from the location that we used in the <script> element of our HTML file.  It won’t work, however.  The problem is that D3 – as it currently stands – does not play nice with Include.js; which Design Studio’s SDK uses to manage diverse javascript packages.  Therefore, Design Studio’s SDK includes a patched D3.  Libraries that ship with Design Studio’s SDK can be accessed via another tag; <stdInclude>, with the attribute indicating the kind of standard include.   So, just above your jsInclude  for the component.js file, add the following line:

<stdInclude kind=”d3″/>

Note.  In our original component setup, we’d already accidentally included it in the provided component.xml, even though it was not mentioned.  So if you simply copied it from there, then it is already in.

Step 2b.2 –

Recall from Step 1.9 of the project setup instalment, that our component.js fille currently looks like this:

sap.designstudio.sdk.Component.subclass(“com.sap.sample.scngauge.SCNGauge”, function() {

     var that = this;

});

Inside of this subclass, we are going to override the init() function of the parent class.  You can leave the contents of the function blank for the moment:

sap.designstudio.sdk.Component.subclass(“com.sap.sample.scngauge.SCNGauge”, function() {

     var that = this;

     this.init = function() {

     };

});

Step 2b.3 –

Let’s start by copying and pasting the PI declaration from step 2a.2 of the last instalment, so that we don’t forget it.  While we’re at it, let’s declare it alongside the that = this declaration, so that it is accessible outside of the init() function.  Our component.js should not look like this:

sap.designstudio.sdk.Component.subclass(“com.sap.sample.scngauge.SCNGauge”, function() {

     var that = this;

     var pi = Math.PI;

     this.init = function() {

     };

});

Step 2b.4 –

As you may recall from step Step 2a.3  of the last instalment, we attached an svg container element to the div that we’d set aside for holding our visualization.  We were looking for a div with the tag “#content” and attaching our svg there.  For review, that line of code looked like this:

var vis = d3.select(“#content”)

                    .append(“svg:svg”)

                    .attr(“width”, “100%”)

                    .attr(“height”, “100%”);

We’ll be doing something conceptually similar inside of our init() function; attaching an svg element to a div and then working with it.  The key difference is that previously, we were working directly with the html document DOM and in Design Studio components, this is a discouraged practice.  You should stay within your component handler, for the sake of security and stability.  (in fact, SAP won’t certify a partner component that goes outside of its handler)  The syntax is slightly different.

We’ll still be using D3’s select method to get our div, but we won’t be passing a tag to it.  We’ll first ask the component handler to giv us the div and we’ll then pass the div itself as the parameter:

var myDiv = this.$()[0];

Let’s break this down.  this is the handler instance.  The $() is a Jquery method for getting the root div within the handler instance. $ is shorthand for Jquery and you’ll often see it in JavaScript code that uses Jquery.  If there is an id parameter, tag parameter, or a css class parameter, we’d take that, but if the S() call has an empty, it will select the root div.  Since this returns a list, we’ll take the first element.   As you may recall from Step 1.9 of the initial project creation instalment, we can’t *always* be certain that this is in fact the component handler and that the scope might have changed on us.  That’s what we declare a variable named that and set it to this,  We’ll use that here, instead of this.

So now we can actually add the line to init():

var myDiv = that.$()[0];

Now that we have the div, we can select it and attach the svg element:

var vis = d3.select(myDiv)

                    .append(“svg:svg”)

                    .attr(“width”, “100%”)

                    .attr(“height”, “100%”);

Step 2b.5 –

Copy and paste the rest of the Javascript code from last time; specifcially the parts from steps 2a.4 and 2a.5.  Your component.js should now look like the following:

sap.designstudio.sdk.Component.subclass(“com.sap.sample.scngauge.SCNGauge”, function() {

     var that = this;

     var pi = Math.PI;

     this.init = function() {

          var myDiv = that.$()[0];

          var vis = d3.select(myDiv).append(“svg:svg”).attr(“width”, “100%”).attr(“height”, “100%”);

          var arc = d3.svg.arc()

                         .innerRadius(0)

                         .outerRadius(70)

                         .startAngle(45 * (pi/180)) //converting from degs to radians

                         .endAngle(3) //just radians

          vis.attr(“width”, “400”).attr(“height”, “400”) // Added height and width so arc is visible

               .append(“path”)

               .attr(“d”, arc)

               .attr(“fill”, “red”)

               .attr(“transform”, “translate(200,200)”);

     };

});

Step 2b.6 –

Start Design Studio in debug mode, with the component project open.  Add the gauge component to the canvas of an otherwise blank DS app.

Screen Shot 2015-10-16 at 14.09.01.png

Note that even though the component is supposedly a 100pc x 100px component, the arc is actually entered on a position offset 200×200 from the origin.  That’s because we’ve hardcoded our gauge’s size and offset and ignore what’s in the properties pane.  In a later instalment, we’ll fix this.

As always, the completed extension (as of part 2) is available as a Github repository.

Next Instalment: Part 3a – Making the Arc Configurable

To report this post you need to login first.

6 Comments

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

  1. Gokulkumar Rajagopal Devika

    Hi David,

    It’s wonderful blog and thank you for writing such a useful blog for everyone.

    I have a query. I am not able to see guage in my component though the javascript is the same as your code.Could you please help me on the same.

    Thanks & Regards,

    Gokulkumar RD

    (0) 
  2. Michael Jennings

    Dear Gokulkumar,

    I had the same problem. I solved copying existing sample project like com.sap.sample.clock provided by SAP, after applying the file changes finally I see the component visibile.

     

    P.S:

    “Remember you have to download the SAP sample of version in accordance with your Design studio”

    Best Regards,

    M.J.

    (0) 
  3. David Stocker Post author

    If something is not rendering, what I always do is debug the javascript.  Set a breakpoint and step through it.  99 times out of 100, it means that an exception is occurring and the script execution is halting.

    (0) 
  4. Sumit Ghanty

    For Design Studio DS_16SP04, <stdInclude kind=”d3″/> is not required to be put. It works without it.

     

    <?xml version=”1.0″ encoding=”UTF-8″?>
    <sdkExtension
    xmlns=”http://www.sap.com/bi/zen/sdk”
    id=”com.sap.sample.scngauge”
    title=”SCN Tutorial Gauge”
    version=”16.4″
    vendor=”SAP”>
    <component
    id=”SCNGauge”
    title=”Gauge”
    icon=”res/icon.png”
    handlerType=”div”
    modes=”commons m”
    propertySheetPath=”res/additional_properties_sheet/additional_properties_sheet.html”>
    <requireJs modes=”commons m”>res/js/component</requireJs>
    <stdInclude kind=”d3″/>
    <initialization>
    <defaultValue property=”LEFT_MARGIN”>40</defaultValue>
    <defaultValue property=”TOP_MARGIN”>40</defaultValue>
    <defaultValue property=”WIDTH”>100</defaultValue>
    <defaultValue property=”HEIGHT”>100</defaultValue>
    <defaultValue property=”color”>blue</defaultValue>
    </initialization>
    </component>
    </sdkExtension>

     

    It working for me with it.

     

    (0) 
  5. Alfons Gonzalez Comas

    Hi David,

     

    Great post. I have tried to execute the most simple version of component code (see below) in a particular situation: the component is located in a panel. Both DS items (the panel and the component it self have width and height set to auto), In this case I am not able to retrive a value for the height.

    width: 1920
    height: 0

     

    Do you have any idea about  how to workaorund the issue? It seems that problem might arise from the fact that the component height has notyet been calculated at the time component.js is executed. How to avoid that? Would be possible (in some way) to ensure that init function is not executed until component size is calculated?

     

    Thanks

    ——————————————————————————————————————————————————————————————————————————————————

    define([“sap/designstudio/sdk/component”, “d3”, “css!../css/component.css”], function(Component, d3, css) {
    Component.subclass(“com.sap.sample.scngauge.SCNGauge”, function() {

    var that = this;

    this.init = function() {

    var myDiv = that.$()[0];
    var vis = d3.select(myDiv).append(“svg:svg”).attr(“width”, “100%”).attr(“height”, “100%”);

    var width = this.$().width(); //960;
    var height = this.$().height(); //500;

    console.log(‘width: ‘ + width);
    console.log(‘height: ‘ + height);

    var pi = Math.PI;

    var arc = d3.svg.arc()
    .innerRadius(0)
    .outerRadius(70)
    .startAngle(45 * (pi/180)) //converting from degs to radians
    .endAngle(3) //just radians

    vis.attr(“width”, width).attr(“height”, height) // Added height and width so arc is visible
    .append(“path”)
    .attr(“d”, arc)
    .attr(“fill”, “red”)
    .attr(“transform”, “translate(200,200)”);

    };
    });
    });

    (0) 

Leave a Reply