Design Studio 1.2 SDK – New approach to a toolbar component using SAPUI5 Handler
This could be considered a part 2 of my original post related to creating a Toolbar component using SAPUI5 Framework. You can read that blog for the rationale behind the toolbar idea (Design Studio 1.2 SDK – Building a SAPUI5 Toolbar)
In this entry I wanted to focus on a different approach for the same component. In the initial attempt, I used SAPUI5 technically to create the component, but without any clear direction on how to render it, I used SAPUI5’s placeAt() function to attach it to my DIV container that the SDK provides, based on known examples to-date. In the subsequent comments on that post, Reiner Hille-Doering mentioned that this may not be the best approach and said that there is a more direct, yet undocumented method.
Based on some subsequent comments in another thread, I think I’ve derived the cleaner method that Reiner may have been alluding to. Below is my (undocumented, unsupported for now, I’d assume) approach at implementing the same toolbar by using the sapui5 handler instead of the div handler.
GitHub Link:
In the component.xml file, I only needed to change handlerType from “div” to “sapui5”. The rest of the changes I will call out below which occured mainly in component.js.
I also used some SAPUI5 documentation I found here:
Documentation/AdvancedTopics/OnTheFlyControlDefinition – SAPUI5 Wiki (TIP CORE User Interface)
The code below clocks in just under 100 lines, and I’ve commented the important functions and details to call out.
sap.ui.commons.Toolbar.extend("com.sample.menu.ToolbarMenu", {
// SAP UI5 Metadata convenience at work - Setter and getter are created behind the scenes, including data binding and type validation
metadata : { // Not to be confused with the Data Source metadata property
properties : {
"name" : "string",
"showCaptions" : {defaultValue : "X", type : "string" },
"buttonClicked" : {defaultValue : -1, type : "int" },
"buttonClickedTitle" : {defaultValue : "Nothing Clicked YET", type : "string" }
}
},
// SAPUI5 Renderer, we can leave it alone
renderer : {
/*render : function(rm, oControl){
alert(oControl.getProperty("buttonClickedTitle"));
}*/
},
// Called by sap.designstudio.sdkui5.Handler (sdkui5_handler.js)
initDesignStudio : function() {
try{
// Make 100 setters and getters until SDK supports properties that are Arrays
for(var i=0;i<=100;i++){
this.btns[i] = {};
for(var meta in this.autoProperties){
this.btns[i][meta] = this.autoProperties[meta];
var setter = "set" + meta.charAt(0).toUpperCase() + meta.slice(1) + i; // Camel Case per SAPUI5 (e.g. setTitle0)
var getter = "get" + meta.charAt(0).toUpperCase() + meta.slice(1) + i; // Camel Case per SAPUI5 (e.g. getTitle0)
// Make setters and getters on the fly
this[getter] = function(meta,i){
return function(s){
return this.btns[i][meta];
};
}(meta,i);
this[setter] = function(meta,i){
return function(s){
this.btns[i][meta] = s;
this.populateIcons();
};
}(meta,i);
}
}
this.setStandalone(false);
this.populateIcons();
}catch(e){
alert(e); // Aw snap
}
},
btns : [], // Button Storage
autoProperties : { // Button Properties and default values
title : "",
visible : false,
enabled : false,
icon : ""
},
// Override default getter for custom logic
getButtonClickedTitle : function(){
if(this.getButtonClicked() < 0) return "[Nothing Clicked Yet]";
return this.btns[this.getButtonClicked()].title;
},
// Override the SAPUI5 setter so that we can instruct the component to redraw some buttons
setShowCaptions : function(v){
this.setProperty("showCaptions",v);
this.populateIcons();
},
populateIcons : function(){ // Main button redraw routine
this.removeAllItems(); // Blow away existing buttons
for(var i=0;i<this.btns.length;i++){ // Recreate all buttons
var b=this.btns[i];
var bt;
if(b && (b.title!=""||b.icon!="")){
if(b.title=="sep") {
bt = new sap.ui.commons.ToolbarSeparator();
}else{
var that = this;
bt = new sap.ui.commons.Button({
text : this.getProperty("showCaptions")?b.title:"",
// lite : true,
tooltip : b.title,
enabled : b.enabled,
visible : b.visible,
icon : b.icon,
press : function(j){
return function(){
that.setProperty("buttonClicked",j);
that.fireDesignStudioPropertiesChanged(["buttonClicked","buttonClickedTitle"]); // SDK proxies these properties, must inform of change
that.fireDesignStudioEvent("onclick");
};
}(i)
});
}
this.addItem(bt);
}
}
}
});
I like this approach better because you can more directly bind the SAPUI5 properties to the SDK Properties exposed in contribution.xml, and override just where needed. Also the component.ztl accounts for the SAPUI5 setters and getters notation (versus how the DIV handler uses a fluent setter/getter notation).
In the GitHub Repo, I also attached a sample Design Studio application project, to show how the functionality is identical to the original implementation using the DIV handler.
Hope this helps any other SAPUI5 guys out there who may wish to get their feet wet with Design Studio 1.2 SDK!
Enjoy.
Hi Michael,
Great post, I'm using it right now.
I have one question, the component that i'm using a data source and I need to manipulate it.
I don't know where to put my code,
I tried
afterUpdate : function(){
alert("test");
},
No luck, on the initDesignStudio the data source is not loaded yet, and
renderer, i probably have to return something, because when i implement it, nothing shows up on the sIreen, what happens when i overwrite it?
Best
Leandro
The sapui5 handler does not make use of afterupdate. You will have to handler any updates to properties in the setter. For example, for metadata, a databound property, if you want to know when it changes, override the default getMetadata and setMetadata functions that are made for you with new ones.
setMetadata : function(v){
alert("Hey there.");
},
getMetadata : function() {
...
}
You can learn more about UI5 getters and setters and how they are autocreated and overridden, such as above, in this link:
Documentation/AdvancedTopics/OnTheFlyControlDefinition – SAPUI5 Wiki (TIP CORE User Interface)
Also, do not confuse the metadata property of ui5 with the metadata property of Design Studio, they are two different things.
Michael,
Thanks again for taking your time to help me.
I noticed that the SAPUI5 respects the order if the properties created, so I coded what I needed on the last property.
Now I'm having another problem, on the contribution.ztl file, I created the following code
String getSelectedValue(){*
return this.selectedValue;
*}
Which I fire when the value is changed on the combobox, with the following code.
that.setProperty("selectedValue",that.getValue());
that.fireDesignStudioPropertiesChanged(["selectedValue"]);
that.fireDesignStudioEvent("onchange");
But it always return undifined when I try to show the result of the function getSelectedValue.
My code is here
https://github.com/olafecorcam/com.leandro.gp.combobox
I'll also post a question on the forum.
Best
Leandro
Your answer is awaiting you here:
Function on contribution.ztl not working