Skip to Content

The integration of HTML islands in CRM BSP applications is available for:

  • SAP WEBCUIF Release 747 SAPK-
  • SAP WEBCUIF Release 748 SAPK-74805INWEBCUIF

You can integrate HTML islands with BSP applications in SAP CRM.

By doing this, you will have an SAPUI5 application that is called from CRM through the HTML island. The HTML island will act as a bridge between the CRM BPS application and the SAPUI5 application. You can create an SAPUI5 application using either SAP Hana IDE or SAP WEBIDE. Here, we will focus on SAP Hana IDE.

Prerequisites

You have created a BSP application. For more information, see https://help.sap.com/saphelp_snc700_ehp01/helpdata/en/46/bb181aab4811d4968100a0c94260a5/frameset.htm

You have the following installed:

  • ABAP Development Tools for SAP Netweaver
  • UI Development Toolkit for HTML5
  • SAPUI5 ABAP Repository Team Provider (Developer Edition)

The back-end SAP system has the following:

  • UI5_731: SAPUI5 Team Provider on 731
  • UISAPUI5: SAPUI5
  • UI_INFRA: SAP UI Integration Infrastructure

Procedure

Create a View Inside a BSP Application

Open an existing BSP application. (transaction: /nBSP_WD_CMPWB) and create a view inside.

  1. Go to Component Structure Browser, select Views and Create
  2. Define the view name
  3. Specify the context node(s)
  4. When selecting the type of view, make sure that you select Table view

In the Properties section, you can select Configuration if you want to display fields in the view.

Create an SAPUI5 Application

You can create the SAPUI5 Application by creating a BSP application from SAP Hana IDE. Before deploying the application, check the following options are available when you right click on the BSP application. Menu Run As:

  • Run On Server
  • Java Applet
  • Java Application
  • Web App Preview

 

Right click on the created BSP application Menu Option Project Menu -> Team -> Share Project:

  • Choose Share and then SAPUI5 ABAP Repository and click on Next to continue
  • Enter the system connection, and choose Next to continue
  • Logon to the back-end system. Here, you can create a new BSP application or select one that has already been created.
  • Select Sever Runtime Version, OK and then select Team -> Submit.

The SAPUI5 application is deployed to the SAP ABAP Server.

You define the HTML island from the CRM BSP application. The idea is to have an SAPUI5 control that is used within a WEBCUIF view. This is done using the declarative tag for the HTML island.

  • To write the logic for the Island, an HTML page and some JavaScript files must be created. In the consuming view, the thtmlbx:htmlIsland tag will contain the path to the static HTML page. In addition, the SAPUI5 logic must be created or uploaded as an HTML file in the MIME repository. The tag for the HTML island refers to the path of this file.

Example

<thtmlbx:htmlIsland id       = “htmltestIsland”
                             height   = “800px”
                              width    = “100%”
                             htmlFile = “/sap(====)/bc/ui5_ui5/sap/islandtest/webapp/index.html” >

The htmlFile property references the SAPUI5 application.

  • The xBCML Renderer component renders the mapped parts of the view content into an xBCML formatted XML document. This XML contains the data that the logic in the SAPUI5 view will consume or render.

Figure 1: Example structure of the CRM BSP Application

  • For the exchange of information between CRM and the SAPUI5 application, the properties and data sources context nodes are required. Events are defined for reacting to user actions.

The htmlIslandProperty node is a normal context node where you must have defined getter and setter. When naming the getter and setter, you must include the name of the property in the name of the function when defining it in the SAPUI5 application.

For example, if the property’s name is boolValue, then the getter and setter are called getBoolValue and setBoolValue respectively.
Example

The definition of the property is done by using the < thtmlbx:htmlIslandProperty > tag name. You can define several properties. Make sure that you define the value with the format //<CONTEXT_NODE_NAME>/<ATTRIBUTE>

   <thtmlbx:htmlIslandProperty id    = “boolValue”
                                             name  = “boolValue”
                                              value = “//PROPERTY/BOOL_PROPERTY” />

The htmlIslandDataSource node is linked with context nodes of type Table. For each data source a getter and setter are created and their names are extensions of the name of the data source. For example, if the data source name is flightData, then the getter and setter are called getFlightData and setFlightData respectively.
Example

The definition of the data source is done using the < thtmlbx:htmlIslandDataSource > tag.

   <thtmlbx:htmlIslandDataSource id   = “sflight”
                                                  name = “sflight”
                                                    data = “//FLIGHT/Table”
                                           properties = “<%= controller->gt_properties %>” />

As you can see in our example we have the properties parameter defined as controller->gt_properties. This is a table where we associate the data source properties with the table context node attributes.

Figure 2: The association of the data with the properties.

Therefore, the GT_PROPERTIES table is defined in the view controller as an Instance Attribute with Public visibility and the Associated Type as WCF_HIT_DATASOURCE_PROPERTY.

A method can be created to define each of those properties and add them to the GT_PROPERTIES table. For instance, the first attribute is CARRID, in the method we define and append the property to the table. We do the same with each of the attributes in the context node.

  ls_property-id = ‘CARRID’.
  ls_property-name = ‘CARRID’.
  ls_property-abap_fieldname = ‘CARRID’.
  APPEND ls_property TO gt_properties.

 

Events are part of the HTML island and allow the communication between the BSP application and the SAPUI5 application by triggering round trips on user interactions. To define an event, the tag <thtmlbx:htmlIslandEvent >.
Example

  <thtmlbx:htmlIslandEvent id       = “refresh”
                                       name     = “refresh”
                                      onAction = “refresh” />

There are two types of events; client events and server events. Client events allow Islands to listen and fire client-side events which don’t necessarily trigger a server request. For more information, see Setup the SAPUI5 Application Interaction with the HTML Island Framework, below. Server events receive and modify data. They have parameters which are passed to the API as a JavaScript object (hashmap) of name value pairs. The name of the server event is the one that will be used in the SAPUI5 application when firing the event.

Summary of Code Details:

  • BSP Application: THTMLB_SCRIPTS
  • island_scripts.js: HTMLIsland includes scripts_htmlisland.js which is the HTML island script
  • New data elements were created in the BSP_DYN_CONFIG_TAG_LIB package.

 

Setup the SAPUI5 Application Interaction with the HTML Island Framework

From the SAPUI5 application, we also need to interact with the HTML island framework for two reasons. The SAPUI5 application must be able to access the context data serialized as xBCML, and secondly, it must be able to trigger a round trip on user interactions and events.

Example

In this example, the application is named ISLANDTEST, and the MVC concept is used. The following process shows how to setup this interaction.

Figure 3: The structure of an application named ISLANDTEST, using the MVC concept

 

 index.html file

In the index.html file,

<script>
//domain relaxation
var liBehindFirstDot = location.hostname.indexOf(“.”)+1;
if (liBehindFirstDot > 0) {
document.domain = location.hostname.substr(liBehindFirstDot);
}
</script>

  • Add the HTML island scripts

<script src=”/sap(====)/bc/bsp/sap/thtmlb_scripts/island_scripts.js?version=1″ type=”text/javascript”></script>
<title>htmlislandtest</title>
<script id=”sap-ui-bootstrap”
src=”resources/sap-ui-core.js” id=”sap-ui-bootstrap”
data-sap-ui-libs=”sap.m, sap.ui.commons, sap.ui.table”
data-sap-ui-theme=”sap_bluecrystal”
data-sap-ui-compatVersion=”edge”
data-sap-ui-resourceroots='{“htmlislandtest”: “”}’
data-sap-ui-debug=”true” >
</script>
<link rel=”stylesheet” type=”text/css” href=”css/style.css”>
</script>

The first line includes the JavaScript files that controls the HTML island. The second script tab is the normal sap-ui-bootstrap used in SAPUI5 applications.

  • In the body of the HTML page, the body onload is defined as onBodyLoad, with the class defined as sapUiBody. The div id is defined as uiArea. This creates the onBodyLoad function.

  <body onload=”onBodyLoad()” class=“sapUiBody” id=“content”>
<div id=“uiArea”></div>
</body>

Here, you assign an object. In this example, it is called App. App receives the div id as a parameter. This object has all the definitions of the getters and setters that are needed to communicate with the BSP application using the HTML island.

var app;
function onBodyLoad() {
app = new App(‘uiArea’); // Create an instance of an App during the onload event handler
}

  • Create the App object and define the attributes and functions.

As you can see, the div id is passed to the App constructor. In the init method, it is passed as an attribute to initialize the App object.

There are several objects defined. Each correspond to every context node in the BSP application and they will hold the data that will be sent to the SAPUI5 application.

function App(rootId) {
 this._boolValue = {};
 this._stringValue = {};
 this._integerValue = {};
 this._floatValue = {};
 this._binaryValue = {};
 this._dateValue = {};
 this._timeValue = {};
 this._sflight = [];
 this._UIConfig = [];
 this.init(rootId);
}

Inside the init method, register the HTML island, create the getters and setters for data interchange and define the client and server events.

  • Register the HTML island.

thtmlbxHIslandLib.register(this);

  • Define variables and models.

Create all the necessary variables and models for the exchange of information. Based on our example, we have the following methods that belong to the island and can be used inside your application.

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_BEGIN_FREEZE, this.onBeginFreeze, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_END_FREEZE, this.onEndFreeze, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_BEGIN_UPDATE, this.onBeginUpdate, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_END_UPDATE, this.onEndUpdate, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_BEGIN_UPDATE_EVENTS, this.onBeginUpdateEvents, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_END_UPDATE_EVENTS, this.onEndUpdateEvents, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_BEGIN_UPDATE_PROPS, this.onBeginUpdateProps, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_END_UPDATE_PROPS, this.onEndUpdateProps, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_BEGIN_UPDATE_DATASOURCES, this.onBeginUpdateDataSources, this);

thtmlbxHIslandLib.addEventListener(thtmlbxHIslandLib.EVENT_END_UPDATE_DATASOURCES, this.onEndUpdateDataSources, this);

//Models

The models, based on the example, would be written as follows:

    // Create the central model(s)
    var model = new sap.ui.model.json.JSONModel();
    model.setData({data: this.getSFlight()}); // initially empty list
    // place the model instance in a central location, available to UI Components as well as the App
    sap.ui.getCore().setModel(model, ‘sflight’);
    var model = new sap.ui.model.json.JSONModel();
    model.setData({data: this.getUIConfig}); // initially empty list
    sap.ui.getCore().setModel(model, ‘UIConfig’);
           var oData = {
               boolVal : ” “,
               timeVal : ” “,
               floatVal : ” “,
               dateVal : ” “,
               binaryVal : ” “,
               intVal : ” “,
               stringVal : ” “
         };

         var oModel = new sap.ui.model.json.JSONModel();
         oModel.setData(oData);
         sap.ui.getCore().setModel(oModel, ‘datamodel’);

 

 

  • Create getters and setters for properties

As explained before, every attribute in the context nodes must have a getter and setter method in the App object because this is how the data is passed from the BSP application to the SAPUI5 application. Above, the property definition for boolValue was used as an example. Here, the getter and setter methods for the same example are shown.

App.prototype.getBoolValue = function() {
  return this._boolValue;
};
App.prototype.setBoolValue = function(val) {
    this._boolValue = val;
    var model = sap.ui.getCore().getModel(‘datamodel’); // get the central model
    model.setProperty(“/boolVal”,val);
    model.updateBindings(true); // let the UI Component know the data has changed
};

As you can see, the name of the getter and setter includes the exact name of the property in the BSP application. It is important to set the value of the property to the model to keep the information and to call the method updateBindings to keep the binding information available.

  • Create getters and setters for data sources

The same logic applies to data sources as properties. Here, the getter and setter methods are shown for the data sources.

// getter for flightData DataSource
App.prototype.getSFlight = function() {
    return this._sflight;
};
// setter for flightData DataSource
App.prototype.setSflight = function(val) {
    var model = sap.ui.getCore().getModel(‘sflight’); // get the central model
    model.setData({data: val});
    model.updateBindings(true); // let the UI Component know the data has changed
    this._sflight = val; // store on the private member variable
};

  • Create client and server events calls

The listener to the client event was previously defined in the Define variables and models section, now we just create the associated function body as follows:

App.prototype.onBeginUpdate = function() {
  logX(‘App1’, ‘onBeginUpdate’);
  // Check some of the parameters
  logX(‘App1’, ‘onBeginUpdate’, ‘Locale: ‘ + thtmlbxHIslandLib.getLocaleString());
  logX(‘App1’, ‘onBeginUpdate’, ‘Decimal Separator: ‘ + thtmlbxHIslandLib.getDecimalSeparator());
  logX(‘App1’, ‘onBeginUpdate’, ‘Grouping Separator: ‘ + thtmlbxHIslandLib.getGroupingSeparator());
  logX(‘App1’, ‘onBeginUpdate’, ‘Date Format String: ‘ + thtmlbxHIslandLib.getDateFormatString());
  var dateFormatField = sap.ui.getCore().byId(‘dateFormatField’);
  if(dateFormatField)
    dateFormatField.setValue(thtmlbxHIslandLib.getDateFormatString());
};

There is only one definition for server events and several events can be called from it.

App.prototype.fireServerEvent = function(name, paramMap) {
    thtmlbxHIslandLib.fireEvent(name, paramMap);
};

As you can see, the name of the event and its parameters are passed to the function that will fire the event to the back-end. The event must be defined in the BSP application.

  • Create the view and place it at the div that has been passed as parameter in the constructor of the App object.

     sap.ui.xmlview({
               viewName : “htmlislandtest.view.View1”
            }).placeAt(rootID);

Associate Models to UI controllers

From the view, associate the created models to the UI controls. For example, a table with the data source as follows:

 <Table id=“idflightsTable” inset=“false” items=“{sflight>/data}”>
            <items>
              <ColumnListItem id=“idflightscli” >
                <cells>
                  <Text text=“{sflight>CARRID}” />
                  <Text text=“{sflight>CONNID}” />
                  <Text text=“{sflight>FLDATE}” />
                  <Text text=“{sflight>CURRENCY}” />
                  <Input value=“{sflight>PRICE}” editable=“true” />
                  <Input value=“{sflight>SEATSMAX}” editable=“true” />
                </cells>
              </ColumnListItem>
            </items>
          </Table>

Here’s an example of how the properties could be defined as follows:

<Label text=“Boolean”/>
<Input width=‘300px’ value=“{datamodel>/boolVal}” enabled=“false”></Input>

 

Controller

From the controller, the events are defined in normal methods or functions for example:

    onRefresh: function() {
      app.fireServerEvent(“refresh”);
    },

This will fire the refresh method. In this case, no parameters are sent, if you need to send parameters you can as follows:

app.fireServerEvent(“confirm”, { BP_NUMBER: sConfirmedBP, CP_NUMBER:sConfirmedCP, SEARCHTERM: sSearchTerm });

When the event is fired, the round trip is performed and the event is triggered in the back-end system. To access the parameters sent, you define a variable type CL_THMLBX_HI_EVENT. The data sent from the SAPUI5 application can be accessed using the get_param_value method. For example,

DATA: lr_event TYPE REF TO cl_thtmlbx_hi_event,
lv_data1 TYPE string.
lr_event ?= htmlb_event_ex.
lv_data1 = lr_event->get_param_value( ‘bp_number’ ).

 

The results from the browser are displayed in the following image:

Figure 4: The left side of the screen shows the BSP application with some data that was passed to the SAPUI5 application, which is shown on the right half of the screen.

On the left side of the screen, is the BSP application with some data that was passed to the SAPUI5 application, located on the right side of the screen. When you modify the data in the SAPUI5 application and choose Refresh, the data will be updated in the BSP application. This is shown in the image below where the value 400 was changed on the right, in the SAPUI5 application and reflected on the left in the BSP application.

Figure 5: The value for the airfair was changed in the SAPUI5 application. After a refresh, the data is updated in the BSP application, seen on the left

To report this post you need to login first.

2 Comments

You must be Logged on to comment or reply to a post.

  1. Dhruvin Mehta

    Hi ,

    Thanks a lot for the very informative blog.

    I am successful in doing it if the UI5 application resides in my server ( i.e in CRM system ) ,

    in our case I want to load the App from a central UX server , now how can i bind the fields to my value nodes and how the fireserverevent calls crm system , and not the Backend system where th app is deployed.

    I hope my question is clear.

     

    Regards,

    Dhruvin

    (0) 
    1. Elsy Mena Post author

      Hi Dhruvin,

      Unfortunately, I have not worked having the SAPUI5 application in a different server yet. In my case both the BSP application and the SAPUI5 application are in the same server.

      But I debugged the fireServerEvent and can let you know what happens.

      When using the fireServerEvent, you just pass two parameters, the server event name and the map with all key-value information you want to use when triggering the event.

      If you want to debug the fireServerEvent, you can find it in island_scripts.js

      Here the call stack, on the bottom the first calls, I put some comments to explain a bit:

      htmlbSubmitLib (events.js?sap-client=001&sap-language=EN&sap-domainRelax=min&20170607202633:322)

      /*The from tag includes <form id=”myFormId” name=”myFormId” method=”post” action=”/sap(..)/bc/bsp/sap/crm_ui_frame/BSPWDApplication.do?sap-client=001&amp;sap-domainrelax=min&amp;sap-language=EN” target=”WorkAreaFrame2__s_001_IC_ITSDAGENT_1512144094334″> */

      C29_W110_V111_SearchHss_C29_W110_V111_confirm (BSPWDApplication.do?sap-client=001&sap-domainrelax=min&sap-language=EN:678) (This is my Island which id is C29_W110_V111_SearchHss and the server event name C29_W110_V111_confirm)

      wcf_fi_fireEvent (scripts.js?sap-client=001&sap-language=EN&sap-domainRelax=min&20171201125436:51057)

      thtmlbx_HIClient.callExternal (island_scripts.js?version=1:1394)

      thtmlbx_HIEventHandler.fireEvent (island_scripts.js?version=1:1756)

      thtmlbx_HIslandCntrl.onAction (island_scripts.js?version=1:2049)

      thtmlbx_HIslandLib.fireEvent (island_scripts.js?version=1:393)//From here up is the island calls

      App.fireServerEvent (index.html?sap-client=001&sap-ui-language=en&sap-ui-rtl=false&sap-ui-accessibility=false&sap-ui-theme=sap_corbu&id=C29_W110_V111_SearchHss:125) //Defintion from App

      onConfirm (SeaSmartSearchMain.controller.js:133)//Normal call from the controller

      a.fireEvent (sap-ui-core.js:449)

      a.fireEvent (sap-ui-core.js:976)

      (anonymous) (sap-ui-core.js:573)

      a.onclick (Link.js:6) //Sending the event through a Link

      a._handleEvent (sap-ui-core.js:961)

      U._handleEvent (sap-ui-core.js:1185)

      p (sap-ui-core.js:38)

      dispatch (sap-ui-core.js:49)

      c3.handle (sap-ui-core.js:49)

       

      The action should be performed here sap(..)/bc/bsp/sap/crm_ui_frame/BSPWDApplication.do

      I would recommend to debug and check the values you are getting and may be from there you can get a hint.

      Hope this information will help you.

      Best regards,

      Elsy

      (0) 

Leave a Reply