Technical Articles
D3 Force Bubble Custom Widget for SAP Analytics Cloud
Hello everyone!! This is my first blog on SAC Custom widgets. Here let me share the custom Force Bubble widget for SAC that I’ve created using D3.js.
In this widget, each data point is represented by a bubble which are plotted on x-axis with help of D3 – Force Layout.
Short Demo:
Features:
Builder panel:
Following configuration options are given in the Builder panel:
1. Data:
Hard-coded data can be fed to the chart with this option. Data to be entered in following format:
[
{"name":"Label 1","size":850.84, "color":50.7, "xvalue":100},
{"name":"Label 2","size":3308.76, "color":10, "xvalue":20.5}
]
- name: The label of the bubble.
- size: The value which is represented by the size of the bubble.
- color: The value which is represented by the color of the bubble.
- xvalue: The value based on which the bubbles are plotted on x-axis.
After the data is keyed in, Set Data button to be clicked to feed the data into the chart.
It is also possible to set the data by script. This is described in the Scripting section.
2. X-Axis label: The label to be used for the measure plotted on x-axis of the chart.
3. Size-Axis label: The label to be used for the measure represented by size of the bubble.
4. Color-Axis label: The label to be used for the measure represented by color of the bubble.
5. Decimal place of value on x-axis: Decimal places to display for the measure plotted on x-axis of the chart.
6. Decimal place of value on size-axis: Decimal places to display for the measure represented by size of the bubble.
7. Decimal place of value on color-axis: Decimal places to display for the measure represented by color of the bubble.
Styling panel:
Following configuration options are given in the Styling panel:
1. Title: The title of the chart.
2. Show Title: Show or hide the title of the chart.
3. Show Average Line: Show or hide the average line in the chart.
4. Define Color Scale: Define the start and end color of the color scale. The lowest value will be represented by start color and the highest value will be represented by the end color.
Event:
onSelect(): void
Called when a bubble is clicked. The widget only supports single selection. The selected bubble to be clicked again to de-select.
Scripting:
In addition to the standard methods inherited from Widget, following methods are available for the component to be used in scripting:
setTitle(text: string): void | Set title of the chart. |
setTitleVisible(flag: boolean): void | Show / hide the title of the chart. |
setAvgVisible(flag: boolean): void | Show / hide the average line in the chart. |
setStartColor(color: string): void | Set the start color of the color scale.
Example:
FBUBBLE_1.setStartColor("#f00");
|
setEndColor(color: string): void | Set the end color of the color scale.
Example:
FBUBBLE_1.setEndColor("green");
|
setXAxisLabel(text: string): void | Set the name to be used for the measure plotted on x-axis of the chart. |
setSizeAxisLabel(text: string): void | Set the name to be used for the measure represented by size of the bubble. |
setColorAxisLabel(text: string): void | Set the name to be used for the measure represented by color of the bubble. |
setValueDecimal(value: integer): void | Set the decimal places to display for the measure plotted on x-axis of the chart. |
setSizeValueDecimal(value: integer): void | Set the decimal places to display for the measure represented by size of the bubble. |
setColorValueDecimal(value: integer): void | Set the decimal places to display for the measure represented by color of the bubble. |
setData(jsonData: string): void |
Set the data to be plotted in the chart. The data to be passed as a string in following JSON format: [ {“name”:“Label 1”, “size”:850.84, “color”:50.7, “xvalue”:100}, {“name”:“Label 2”, “size”:3308.76, “color”:10, “xvalue”:20.5} ] Example:
FBUBBLE_1.setData('[{"name":"Label 1","size":850.84, "color":50.7, "xvalue":100},{"name":"Label 2","size":3308.76, "color":10, "xvalue":20.5}]');
|
getSelectedLabel(): string |
Returns the label of the selected bubble when a bubble is clicked. When de-selected, this method returns undefined. |
getSelectedXValue(): number |
Returns the x-axis value of the selected bubble when a bubble is clicked. When de-selected, this method returns undefined. |
getSelectedSizeValue(): number |
Returns the size-axis value of the selected bubble when a bubble is clicked. When de-selected, this method returns undefined. |
getSelectedColorValue(): number |
Returns the color-axis value of the selected bubble when a bubble is clicked. When de-selected, this method returns undefined. |
How to prepare data for the chart:
As of now, there is no option to bind a custom widget with a data source. Hence, we have to feed data to the widget dynamically using the setData method. Here is an example on how to prepare the data in desired format before feeding to this custom widget:
Step #1:
Insert a table in the canvas with one or more dimensions and minimum three measures. In this example, I have taken Product as dimension and Units_Sold, Sales_Value and Discount as measures.
Step #2:
Create a Script Function createJSONData(): string as below:
var DS_1 = Table_1.getDataSource();
var dimList = DS_1.getMembers("Product",100);
var json = "";
for(var i = 0; i < dimList.length; i++){
var label = '"name":"'+dimList[i].id+'"';
var value = DS_1.getData({
"@MeasureDimension":"[Account].[parentId].&[Sales_Value]",
"Product":dimList[i].id
});
var svalue = DS_1.getData({
"@MeasureDimension":"[Account].[parentId].&[Units_Sold]",
"Product":dimList[i].id
});
var cvalue = DS_1.getData({
"@MeasureDimension":"[Account].[parentId].&[Discount]",
"Product":dimList[i].id
});
var val='';
var sval='';
var cval='';
if(value === undefined || svalue === undefined || cvalue === undefined){
// Do nothing
}else{
val = value.rawValue;
sval = svalue.rawValue;
cval = cvalue.rawValue;
json = json + "{" + label + "," + '"xvalue":' + val + ","+'"size":' + sval +',"color":'+cval+"},";
}
}
json = "[" + json.substring(0,json.length-1) + "]";
return json;
Step #3:
Call following script in Application – onInitialization (and if required, in Table_1 – onResultChanged) to feed the data into the custom widget:
FBUBBLE_1.setData(ScriptObject_1.createJSONData());
If the table is not to be displayed, we can hide the table with:
Table_1.setVisible(false);
Code:
The code is available here if you are interested to have a look:
Hi Arjit,
Thanks for the informative blog.
Is there any information on how to connect Custom widget to a model?
Regards
Ramu
Hi Ramu,
Unfortunately, binding a custom widget directly to a model is not possible as of now. This is a limitation of SAC at present. That's why in this example we have used script to feed the data to the widget.
Regards,
Arijit
Hi Arijit,
Thanks for the wonderful blog.
I am new to this world and would like to know how can I utilize the existing chart libraries for eg. D3, AMcharts etc. As the third party libraries are available in the combination of HTML+JS+CSS, but the code you have provided here in the form of web component.
Regards,
Shimon
The extension for SAC Analytic Designer is created as web component. You can easily use D3, AMCharts etc to create the main component. In this example, I have used D3 and lodash third party libraries.
Hello Arijit,
Thanks for the reply. Are their any tutorials available to create the main component for D3 or AMcharts. Could you please share some links.
Thanks and regards,
Shimon
The only tutorial that I found was the official product documentation from SAP (https://help.sap.com/viewer/0ac8c6754ff84605a4372468d002f2bf/release/en-US).
You can also follow the blogs from Ferry Djaja.
Regards,
Arijit
Hi Arijit,
This is a great tutorial, is there any update or functionality now to support connecting a custom widget to a dataset or model within SAC?
Regards,
Barry
Thanks Barry.
Unfortunately binding a custom widget directly with a data source is still not possible. I am unable to find anything regarding this in the roadmap as well.
Regards,
Arijit
That's very unfortunate. Do you know of any charting libraries that facilitate connecting a custom widget to a dataset or model?
Regards,
Barry