Skip to Content
Author's profile photo Former Member

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:

Without the CSS With CSS dynamically generated CSS code
Screen Shot 2016-07-01 at 5.26.42 PM.png Screen Shot 2016-07-01 at 5.23.14 PM.png

<style>

.colorList li:nth-child(1) * {background-color:#ff5d17 !important;}

.colorList li:nth-child(2) * {background-color:#ff8d00 !important;}

.colorList li:nth-child(3) * {background-color:#ffd141 !important;}

.colorList li:nth-child(4) * {background-color:#23b7ff !important;}

.colorList li:nth-child(5) * {background-color:#0092ff !important;}

</style>

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
Screen Shot 2016-07-01 at 6.02.54 PM.png Screen Shot 2016-07-01 at 5.23.35 PM.png

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);






Assigned Tags

      11 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Mustafa Bensan
      Mustafa Bensan

      Great stuff, Franck!  A very innovative use of Community SDK components and I also like the non-DOM hack approach 🙂

      Author's profile photo Former Member
      Former Member

      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?
      ERROR .PNG

      Regards

      Rahul

      Author's profile photo Thibault ROBIN
      Thibault ROBIN

      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

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      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.

      Author's profile photo Michael Howles
      Michael Howles

      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.

      Author's profile photo Former Member
      Former Member

      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

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      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.

      Author's profile photo Michael Howles
      Michael Howles

      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 🙂

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      Thanks Mike 🙂 I guess if the rapid Prototyping would be an issue on production, we could create a CSS generator component.

      Author's profile photo Former Member
      Former Member

      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.

      Author's profile photo Former Member
      Former Member
      Blog Post Author

      You'll find it under Community Prototypes:

      Screen Shot 2016-07-28 at 12.45.02 PM.png

      You need to have them installed beforehand (they're optional)