Generate CSS code dynamically in Design Studio with the Community Package
Hello,
I would like to share with you a method for implementing dynamic styles on any components, either standard or not, through 2 examples. It requires good scripting and CSS knowledge.
Pros:
- No DOM hacking/modifications: No other component HTML code is modified
- Only CSS, but very powerful: Any part of the application can be accessed with the selectors
- Dynamic: Can be controlled by the application
- Compatible with IE and Chrome: Works like a charm in both
What do you need ? Rapid Prototyping Component from the SCN SDK Community Package For Design Studio !
These other components are optional:
- Array: Only way to have a real global table in your application (except storing it in CSV String format)
- Data Iterator: If you want to link the CSS to Datasource data
Don’t hesitate to download the test application shown below here (Build for DS 1.6 SP2 P1)
Here’s a quick demo with some comments:
PS: sorry for my french accent
Use-case 1: Custom Color Palette
I wanted to get a full color customizable color palette in DS. To do that, I used:
- Buttons: up, down, +, delete etc …
- Array component: easy manipulation of the entries
- Palette component to let the user choose the color
The last important feature would be to change the color of each list element:
It’s actually quite easy to generate the CSS to get this display. Each entry of the list is a LI, and we just need to address each of the with its line number (using li:nth-child() selector) and apply the associated background color.
You can also use the attribute data-sap-ui-lvx-index the selector nth-child 🙂
HTML Code associated to the list:
<div id="LIST_COLORS_ddlb" data-sap-ui="LIST_COLORS_ddlb" tabindex="-1" class="sapUiLbx sapUiLbxFixed sapUiLbxStd zenControl zenTempFixForListBox colorList" style="width: 200px; height: 100%;">
<ul id="LIST_COLORS_ddlb-list" tabindex="-1" role="listbox" aria-multiselectable="false" aria-activedescendant="__item3">
<li id="__item0" data-sap-ui="__item0" data-sap-ui-lbx-index="0" tabindex="-1" class="sapUiLbxI" title="#ff5d17" role="option" aria-selected="false" aria-setsize="5" aria-posinset="1"><span class="sapUiLbxITxt" id="__item0-txt" style="text-align:left">#ff5d17</span></li>
<li id="__item1" data-sap-ui="__item1" data-sap-ui-lbx-index="1" tabindex="-1" class="sapUiLbxI" title="#ff8d00" role="option" aria-selected="false" aria-setsize="5" aria-posinset="2"><span class="sapUiLbxITxt" id="__item1-txt" style="text-align:left">#ff8d00</span></li>
<li id="__item2" data-sap-ui="__item2" data-sap-ui-lbx-index="2" tabindex="-1" class="sapUiLbxI" title="#ffd141" role="option" aria-selected="false" aria-setsize="5" aria-ponset="3"><span class="sapUiLbxITxt" id="__item2-txt" style="text-align:left">#ffd141</span></li>
<li id="__item3" data-sap-ui="__item3" data-sap-ui-lbx-index="3" tabindex="0" class="sapUiLbxI sapUiLbxISel" title="#23b7ff" role="option" aria-selected="true" aria-setsize="5" aria-posinset="4"><span class="sapUiLbxITxt" id="__item3-txt" style="text-align:left">#23b7ff</span></li>
<li id="__item4" data-sap-ui="__item4" data-sap-ui-lbx-index="4" tabindex="-1" class="sapUiLbxI" title="#0092ff" role="option" aria-selected="false" aria-setsize="5" aria-posinset="5"><span class="sapUiLbxITxt" id="__item4-txt" style="text-align:left">#0092ff</span></li>
</ul>
</div>
I just added .colorList class to the list and called this script each time a modification is done:
var style = "<style>\n";
//Loop on the different colors in the list (stored in an array)
ARRAY_COLORS.getValuesAsSimpleStringArray().forEach(function(element, index) {
var ind2 = index + 1; //CSS index starts at 1 when array starts at 0
//Generate a CSS style for each list entry, using nth-child to refer to each line
style = style + ".colorList li:nth-child(" + ind2 + ") * {background-color:" + element + " !important;} \n";
});
style = style + "</style>";
TA_GEN_CSS.setValue(style);
if (!CB_CSS_PALETTE.isChecked()) {
style = "";
}
//Include the CSS style in the HTML
RAPID_PROT_COLORS_CSS.setHTML(style);
Use-case 2: Crosstab customizing with indicators
Just to demonstrate we can also work on standard components, I will show you how to change alter the style of a cross tab like that:
Normal Crosstab | Customized Crosstab |
---|---|
![]() |
![]() |
Again, the CSS is different from DOM hacking, therefore limits any serious issues.
The most difficult part is to get the working CSS, and I recommend testing it in Chrome or IE in debug before.
The first cell (Billed quantity) needs to be referenced by this path:
.dynamicCT #CROSSTAB_1_dataArea tbody tr:nth-child(1) td:first-child div.sapzencrosstab-DataCellContentDiv
The TR corresponds to each of the lines (and the number will need to be dynamic), the TD corresponds to the columns, i.e. Billed quantity, and finally the div contains the measure value.
The algorithm is:
- Loop at each line
- Calculate %variance between Current Year and Last Year Billed quantity
- if %variance is greater than threshold then:
- If negative: display a red down arrow in front
- If positive: display a green up arrow in front
- Add after the measure value the %variance in parenthesis
Note: that Pixel based display must be activated to work.
Note 2: The script is at the end.
So, as a conclusion, only the CSS functionalities and your imagination can limit what you can do. Please do comment if you like it or if you have any questions ! 😉
Thank you for reading.
And finally the script:
//Data Iterator: get all the rows
var rows = DATA_IT.getRows();
//Get the threshold from the Input Field
var thresh_u = Convert.stringToFloat(IF_THRESH.getValue());
var thresh_d = thresh_u * -1;
//Start the Style Markup
var content = "<style>\n";
//Hide PY billed qty
content = content + " .dynamicCT table.sapzencrosstab-ColumnHeaderArea * tr.sapzencrosstab-HeaderRow td:nth-child(3) { display: none}\n";
content = content + " .dynamicCT #CROSSTAB_1_dataArea tbody tr td:nth-child(3) { display: none}\n";
//Loop at each entry from the datasource
rows.forEach(function(element, index) {
//Get measure Billed quantity and Previous Year Billed Quantity
var mes = element.getMeasureValue("BILLED_QUANTITY");
var mes_ly = element.getMeasureValue("PREV_BILL");
//always add 1 to the array index because the CSS starts at 1. This index will bu used to address the correct line
var index2 = index + 1;
var diffpc = 0.0;
//calculate the difference in percentage
if (mes_ly != 0) {
diffpc = (mes - mes_ly) / mes_ly * 100;
diffpc = MATH_1.round(diffpc);
}
var sign = "";
if (diffpc < thresh_d) {
//Percentage value is below -Threshold
var id = ".dynamicCT #CROSSTAB_1_dataArea tbody tr:nth-child(" + index2 + ") td:first-child div.sapzencrosstab-DataCellContentDiv:before ";
content = content + id + " \n{ content:url(http://www.exilim.eu/global/images/red-arrow-down.png);}\n";
} else if (diffpc > thresh_u) {
id = ".dynamicCT #CROSSTAB_1_dataArea tbody tr:nth-child(" + index2 + ") td:first-child div.sapzencrosstab-DataCellContentDiv:before ";
content = content + id + " { content:url(https://upload.wikimedia.org/wikipedia/commons/4/48/Icons-mini-arrow_up.gif);}\n";
sign = "+";
}
id = ".dynamicCT #CROSSTAB_1_dataArea tbody tr:nth-child(" + index2 + ") td:first-child div.sapzencrosstab-DataCellContentDiv:after ";
content = content + id + " \n{ content:' (" + sign + diffpc + "%)';}\n";
});
content = content + "</style>";
TA_GEN_CSS2.setValue(content);
if (!CB_CSS_CT.isChecked()) {
content = "";
}
//Insert the HTML content in the page
RAPID_PROT_COLORS_CSS2.setHTML(content);
Great stuff, Franck! A very innovative use of Community SDK components and I also like the non-DOM hack approach 🙂
Hi,
I am getting the Error that "The Exported application has been created with a newer version of design tool and potentially contains unknown content. I am currently using Design Studio Release 1.6 Version 16.0.5. What version are you using?

Regards
Rahul
Hi Rahul,
The application is build on DS 1.6 SP2 P1 (Version 16.2.2). You have to upgrade your currently version to SP2 if you want to open it correctly.
Regards
Thibault
Hi Rahul,
Yes, it has been created with SP 6 P1. I think you could unzip the template and change the version in the .biapp and export.properties files corresponding to your. Nothing fancy from SP2P1 has been used, so it should work.
Export one of your app, extract it and have a look at the value in the field version.
You also have to modify the export.properties file (if Franck exported it), simply change the DS version in both files from 1601 to 1600, for example.
Hi Mike,
I changed in the "content.biapp" & it works fine but the data source is not working giving an error failed to instantiate data source. Is this the reason I didn't changed in the export. properties If yes can you please help in which editor have to edit the "export.properties" file
Regards
Rahul
Rahul,
Eventually, it doesn't matter for the datasource. You can remove it and replace it with one of yours with some adjustment in the BIAL scripts, and reassigning the DS to the components.
Franck,
This is awesome! I finally got back to watching the YT vid. Clever use of CSS with the content pseudo-selectors at the end to show percentages 🙂
Thanks Mike 🙂 I guess if the rapid Prototyping would be an issue on production, we could create a CSS generator component.
Hi. Thank you for this post. I couldn't find the rapid prototyping component in the component list. Can you please send me the link. Thanks.
You'll find it under Community Prototypes:
You need to have them installed beforehand (they're optional)