Technology Blogs by SAP
Learn how to extend and personalize SAP applications. Follow the SAP technology blog for insights into SAP BTP, ABAP, SAP Analytics Cloud, SAP HANA, and more.
cancel
Showing results for 
Search instead for 
Did you mean: 
Karol-K
Advisor
Advisor
0 Kudos

This is the description of the way to Online Composition Version 2. I will focus here on "how" I got the functionality coded, not on "what". The "what" functionality can be found in the separated blog here:

Starting from the first application, I still had some more ideas, especially in the area of dynamic in the composition space.

To remind, this is the first application - Community SDK: First Functional Application with SDK Components (Online Composition)

Online Composition is allowing creation of custom applications, but w/o some tricks once the fragment is placed in the split cell container, the access to the fragment is restricted as it can only call the outside part of the application, but the application cannot easily access the fragment.

This explanation of this dynamic part is based on the application described here: Community SDK: Second Functional Application with SDK Components (Online Composition v.2)

What was achieved?

  • binding of the fragments to the application
  • outside-in manipulation of those fragments
  • manipulation of the dynamically created data source which is part of the fragment

The way to..

Here is the description how you can manage to "register" fragments back to the application and access the content objects from outside.

The journey starts with the button "Bind Fragment":

My idea behind was simple - Design Studio offers global script functions, so I have placed the call from this button into a central function, like this:


SCRIPT_FRAGMENT.onContentSettings(CONTENT_XY_SETTINGS_BUTTON, CONTENT_XY_MENU_BUTTON,
     DS_M, CONTENT_XY_CHART, CONTENT_XY_CROSSTAB, CONTENT_XY_TITLE_TEXT,
     PANEL_CONTENT, CONTENT_XY_TOP_PANEL);


By this trick the fragment can pass all its content into the global function - and then you could directly influence the components. But this was not the goal I had, I wanted to be able to influence the content from any place from the application. So I have searched for an option how to save the information and make accessible - the answer was the usage of the Design Studio SDK: Component Manager (for dynamic component access).

With this script I could read out the data source and pass it to the component manager - here the script:


if(oSource.getSelectedKey() == "BIND") {
// add data source to the list of all data sources which are bound
COMPOSE_MANAGER.addDataSourceReferenceToGroup("COMPOSE-" + COMPOSE_PAGEBOOK_CONTENT.getSelectedPage() + "-" + "DS", dataSource);
// mark the fragemnt as bound and add the unbind script
  oSource.addItem("UNBIND", "Unbind Fragment", "sap-icon://pushpin-off");
  topPanel.setCSSClass("binded");
}


at the same point I modify the oSource, which is the button with "Bind Fragment" option and add there an "Unbind Fragment" option.


if(oSource.getSelectedKey() == "UNBIND") {
  COMPOSE_MANAGER.removeDataSourceReferenceFromGroup("COMPOSE-" + COMPOSE_PAGEBOOK_CONTENT.getSelectedPage() + "-" + "DS", dataSource);
  oSource.removeItem("UNBIND");
  topPanel.setCSSClass("");
}


Now, the user can see that this fragment is bound (different CSS on top panel) and has also the option to unbind the fragment.

How can we used the information?

The component manager has now an array of the data sources (for today I worked only on data sources with this functionality) under the key:

"COMPOSE-" + COMPOSE_PAGEBOOK_CONTENT.getSelectedPage() + "-" + "DS"

With this key I can now access the array at any place I want.

Before showing the filter panel in compose room, I save external filters for each dimension - later I will use it to check which dimension was changed by the user (see Copy of Filters below). The code to save the current filters:


COMP_FILTER_COLLECTION.removeAllItems();
var dimensions = DS_C.getDimensions();
dimensions.forEach(function(dimension, index) {
   var filter = DS_C.getFilterExt(dimension);
   COMP_FILTER_COLLECTION.addItem(dimension.name, filter, 0.0);
});

My goal was to allow the filter on bound fragments in the composition (on visible page) - so my use of it is in the filter component. I need to add, that this filter component is based on the data source DS_C which is used to handle the filters.

and the filter component has following script:


var dataSources = COMPOSE_MANAGER.getDataSourcesFromGroup("COMPOSE-" + COMPOSE_PAGEBOOK_CONTENT.getSelectedPage() + "-" + "DS");
// DEBUG_S.log("Length DataSOurces: " + dataSources.length);
dataSources.forEach(function(element, index) {
  var source = element.datasource;
  SCRIPT_LOGIC.composeFiltersTransfer(source);
});


In this script I can pick up the array of all data sources and loop on them.


Copy of Filters

In this case I have created a special function to copy filters of only changed dimensions:


var dimensions = DS_C.getDimensions();dimensions.forEach(function(dimension, index) {
   if(!dimension.isMeasuresDimension) {
      var filter = DS_C.getFilterExt(dimension);
      var lastFilter = COMP_FILTER_COLLECTION.getLabelByKey(dimension.name);
   
      // transfer only if different
      if(filter != lastFilter) {
         target.setFilterExt(dimension, filter);
      }
   }
});

In this script, we have a loop on the dimensions of DS_C and compare the filters on the dimension with the filters before change - those which are not matching any more are transferred, others ignored.

Finally, after the change is done, user can unbind the fragment again.

Summary

With this, the user can:

  • mark some fragments and bind it to the composition
  • change filters on this fragment
  • assure that only this dimension is changed which was actively adjusted in the filter panel

I hope this helps you to make more dynamic applications in the future...

Have fun!