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

We now have a primitive gauge component.  It is static, however, and we’d like to make it dynamic.  There are a couple of ways that we can do this.  One is to use data binding and bind the gauge value directly to one of the measures in a  data source.  We’ll cover that in the next installment.  This time, we’re going to make the gauge scriptable.  Specifically, we’re going to make some of its properties available for display and modification via the Design Studio scripting language.

Extending the Design Studio scripting language to make a component scriptable is a fairly simple process:

  • You write your JavaScript; that you want to execute in Design Studio’s script engine.
  • You package this JavaScript into a domain specific language, called Zen Template Language (ZTL).
  • This ZTL gets packaged into a file, called contribution.ztl.  contribution.ztl goes into the same directory as contribution.xml.

This is an example of a ZTL snippet:

class com.sap.sample.customcomponent.Customcomponent extends Component {

  void customMehtod() {* //Some Javascript *}

}

At first glance, ZTL looks like Java.  If you are familiar with Java, it looks like you are creating new subclass, called Customcomponent and that this is extending Component .  Apparently, the new class is implementing a new method, called customMethod() and probably inheriting a number of others.  So far, so Java.  Then you look inside the brackets and you have JavaScript.  Clearly, this won’t work as a Java class, at least out of the box.  What the Design Studio framework is using the information parsed from the Javaesque wrapper to extend the Editor’s syntax library.  How exactly it does this is not in any publicly exposed API, however, you can interact with it by understanding the anatomy of a ZTL method declaration.

Anatomy of a ZTL Method Declaration

Let’s examine two methods; a setter for the start angle of the gauge and a getter for the end angle.

/* Returns the end angle of the gauge. */

float getEndAngleDeg() {*

  return this.endAngleDeg;

*}

/* Sets the start angle of the gauge. */

void setStartAngleDeg(/* New angle */ float newAngle) {*

  this.startAngleDeg = newAngle;

*}

The comment block at the top of any method declaration becomes the documentation text for the method, in the Design Studio script editor.

Docu.png

The return value type and method name.  There are five values return types; void (nothing will be returned), String, int, float and boolean.  Yes, String is capitalized, while the other return types are not.

Constructor.png

If it has input parameters, then you can put a comment block in to add a description of the parameters in the designer.

ParamDocu.png

If it has input parameters, then these also need to go into the parenthesis, following the method name.

Param.png

The parse-enclosure separates the ZTL from the JavaScript payload.  The Design Studio SDK framework will know to treat everything between {* and *} as JavaScript.

ParseEnclosure.png

Of course, you need the actual JavaScript as well.  Remember that it operates within the context of the component, so this is the component.  An important point to remember here is that this JavaScript code does *not* run in the user’s browser.  In runs in Design Studio’s JavaScript engine, which means that you only have access to raw JavaScript and nothing from the component’s DOM.

JavaScriptBody.png

This gives us the added script methods, when we are working with the component in the designer.  We also have full documentation for these methods.

EditorHelp.png

Extending SCNGauge

SCNGauge has several properties, but we don’t want to expose all of them to scripting at runtime:

  • The offset properties and outerRadius are not shown in the designer, because they are calculated.  For the same reason, we’ll not expose them to the Design Studio scripting language either.
  • The outer radius is calculated.  Unless we want to implement the appropriate defensive error checking – and we don’t want to in this tutorial – it is best not to allow the designer to set the inner radius via script.  Let’s leave that to the design time, where she already gets a warning if she tries to use an invalid value.
  • As with outer radius, we’d have to implement quite a bit of defensive programming if we exposed these to scripting.  In fact, we spent the last four installments implementing a padding visualizer in the additional properties sheet to help with design.  Let’s also leave these out.

This leaves us with three properties, that we’ll be creating getters and setters for:

  • startAngleDeg
  • endAngleDeg
  • colorCode

We don’t have Color available as one of the data type options, but a string will suffice.  Following the rules defined above, the six methods (3 getters and 3 setters) are straightforward.  The entire contribution.ztl file is 33 lines long; including comfortable line spacing.

class com.sap.sample.scngauge.SCNGauge extends Component {

  /* Returns the end angle of the gauge. */

  float getEndAngleDeg() {*

  return this.endAngleDeg;

  *}

  /* Sets the end angle of the gauge. */

  void setEndAngleDeg(/* New angle */ float newAngle) {*

  this.endAngleDeg = newAngle;

  *}

  /* Returns the start angle of the gauge. */

  float getStartAngleDeg() {*

  return this.startAngleDeg;

  *}

  /* Sets the start angle of the gauge. */

  void setStartAngleDeg(/* New angle */ float newAngle) {*

  this.startAngleDeg = newAngle;

  *}

  /* Returns the current color of the gauge. */

  String getColor() {*

  return this.colorCode;

  *}

  /* Sets the current color of the gauge. */

  void setColor(/* New color */ String newColor) {*

  this.colorCode = newColor;

  *}

}

That’s it!  We don’t have to edit any files other than contribution.ztl.

Testing

When we test, we’ll leave these three properties (or set them if needed in the properties pane):

  • Start Angle = -90.0
  • End Angle = 90.0
  • Color = blue

We’ll add a button to our app.

AppInDesigner.png

In the On Click event of the button, we can now add the following script (and the value help should work for method calls).  It will set the starting and ending angles to 45 degrees to the left and right (respectively) of the 12 O’Clock position and turn the gauge red.

SCNGAUGE_1.setStartAngleDeg(-45.0);

SCNGAUGE_1.setEndAngleDeg(45.0);

SCNGAUGE_1.setColor(“red”);

When we test it at runtime, we should first see the image below, left; a blue semicircle.  When we click on the button, it should turn into a red quarter circle.

Results.png

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

Next time, we’ll add data binding.

To report this post you need to login first.

2 Comments

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

  1. Nikolaus Weiss

    Can I set the values of parameters in my component.js file (using the getter/setter functions) and then access values in the contribution.ztl file?

    Example:

    contribution.xml (no defaultValue is set)

    <property 
    id="selectedElement" 
    title="Selected Element" 
    type="int" visible="false"/>

    component.js

    var that = this;
    
    that._selectedElement = 0;
    
    that.selectedElement = function(val) {
    	if (val === undefined) {
    		return that._selectedElement;
    	} else {
    		that._selectedElement = val;
    		return this;
    	}
    };
    
    // var x is assigned int value
    
    that.selectedElement(x);

    contribution.ztl

    /* Returns the index of the selected item */
    int getSelectedMember(){*
    	return this.selectedElement;
    *}

    Now when I use .getSelectedMember() in my script, I expect it to return the values I set in my component.js (var x). Instead, it always returns 0.

    Are there errors in my code, or is it simply not possible to pass parameter values between the .ztl and .js files?

    (0) 
  2. Lorenz Wiest

    You just missed one tiny bit: When you change a property value in the component.js JavaScript (in the browser frontend), you need to notify the Design Studio Runtime (server) to fetch this new value from the frontend. After having fetched the new value fro the frontend, the Design Studio Runtime stores it, so that ZTL methods can retrieve it.

    You can achieve this notification by calling the firePropertiesChanged function in the component.js JavaScript:

    // somewhere in a function of your component.js JavaScript code
    var i = 13245;
    that.selectedElement(x);
    that.firePropertiesChanged(["selectedElement"]);
    

     

    (0) 

Leave a Reply