Additional Blogs by SAP
cancel
Showing results for 
Search instead for 
Did you mean: 

Introduction

In this post we will build an application containing an input field with a Value Help dialog. For that, we will implement a Gateway Query Service that returns the requested list of values. Then we will implement a dialog window with a table in it. With a line selection, we will implement an event which closes the dialog and transmits the selected value to the original input field.

Installed components

We used SAP UI5 v1.12, NetWeaver Gateway 2.0 SP6 and the current version of the Chrome Browser.

Gateway Service Implementation

As of NetWeaver Gateway 2.0 SP4 it is recommended to use the Gateway Service Builder to model the Gateway service Entity Data Model (EDM) [1]. The SEGW is the transaction for that. There we create a new project ZMATNR_VALUE_HELP for the value help service.

We will need one entity MaterialCode for our Value Help Service which contains three properties: material number, material type and description.

For that, we create the Entity MaterialCode along with the related EntitySet MaterialCodeSet:

Next, we select the created entity and define the properties Matnr, Mattype and Descr:

We define the Matnr property as the key property.

All properties have defined EDM type, max length, label, ABAP field and ABAP type.

We define the ABAP Type as a Data element, MATNR, MTART, and MAKTX respectively.

The model is finished now, and we can generate the runtime objects – use icon in the menu bar. 

We keep the proposed names and generate the ABAP classes.

Check if the generation log is green.

Now we select the data provider class (ending with _DPC_EXT):

When double-click on the name we switch to the class builder. We need to redefine the method MATERIALCODESET_GET_ENTITYSET there.

For simplicity, we put the SELECT statement fetching the data directly from MARA/MAKT tables. In the real life, you would usually call a BAPI or any other business function here fetching the values and mapping them to the service entity (represented by the exporting parameter et_entityset).

METHOD materialcodeset_get_entityset.
    SELECT m~matnr m~mtart t~maktx
       INTO CORRESPONDING FIELDS OF TABLE et_entityset
       FROM ( mara AS m
         LEFT OUTER JOIN makt AS t ON m~matnr = t~matnr )
         UP TO 30 ROWS.
ENDMETHOD.

Now we can leave the class and the service builder and go to the Gateway hub (which is in our case the same system). On the Gateway hub we publish the service into the service catalog. For that, we use the transaction /IWFND/MAINT_SERVICE and open up the dialog to add a new service, then provide a system alias for the backend system (for local services we use the alias LOCAL).

We keep all values default and get the service published as follows:

Note: (1) ODATA ICF node must be green, and (2) the System Alias must contain a system alias pointing to the backend system where we created the model and data provider.

Now the service is ready to use and we can test it in the Gateway Client (check the button within the ICF Nodes area).

We change the URL to /sap/opu/odata/sap/ZMATNR_VALUE_HELP_SRV/MaterialCodeSet?$format=json

Then execute the service and check its output.

In our case we’ve got the following JSON document.

In our SAP UI5 application we will use this service for fetching the Material codes and descriptions. 

Note, that we have requested the output in the JSON format ($format=json) as this format is directly supported by JavaScript and SAP UI5.

SAP UI5 Application

Our SAP UI5 project’s name in Eclipse is ValueHelp. It contains an initial Javascript view “main”. This is how our project structure looks like:

As we are going to use the UI5 controls ToolPopup and Table, we need to load the relevant UI5 libraries. For that, we need to include them in the so-called bootstrap declaration. We open the index.html and extend the script parameter data-sap-ui-libs with two more libraries sap.ui.table and sap.ui.ux3.

<script src="resources/sap-ui-core.js"
             id="sap-ui-bootstrap"
             data-sap-ui-libs="sap.ui.commons,sap.ui.table,sap.ui.ux3"
             data-sap-ui-theme="sap_goldreflection" >
</script>

As the next step we update the main.view.js file and implement the function createContent().  We will implement the input field with the UI5 control sap.ui.commons.ValueHelpField and display a field label with another UI5 control sap.ui.commons.Label

We also use some layout controls Panel and LayoutMatrix to make the application appearance nicer.   

  createContent : function(oController) {

      var oPanel = new sap.ui.commons.Panel({
              text : "Select Material Number"
      });

      var oLayoutMatrix = new sap.ui.commons.layout.MatrixLayout({
                          width : "60%",                         // control width relative to window
                          widths : [ "30%", "40%", "30%" ]  // widths of the columns
      });

      var oMatnrLabel = new sap.ui.commons.Label("idMatnrLabel",
              {text: "Material Number"});

      // Input Field for Material Number with Value Help
      var oMatnrInput = new sap.ui.commons.ValueHelpField("idMatnrInput", {
            valueHelpRequest: function(oEvent){
            }          
      });
    
      oLayoutMatrix.createRow(oMatnrLabel, oMatnrInput);
      oPanel.addContent(oLayoutMatrix);
      return oPanel;
  }

The output in Chrome looks now as follows.      

The control ValueHelpField has an event valueHelpRequest which we implement as a dialog window provided by the UI5 control ToolPopup

valueHelpRequest: function(oEvent){
    var oValueHelpDialog = new sap.ui.ux3.ToolPopup({
                        modal: true,
                        inverted: false,                          // disable color inversion
                        title: "Select Material Number",
                        opener:  "idMatnrInput",             // locate dialog next to this field
                        closed: function (oEvent) {
                    }
          });
}

Note: the control event closed is not yet implemented; we will do it later to extract the selected value from the table which will be placed in the dialog window.    

Now we add a button “OK” to the Dialog window which is used to close the dialog window. This code is placed directly after the declaration of oValueHelpDialog

var oOkButton = new sap.ui.commons.Button({
                        text: "OK",
                        press: function (oEvent) {
                                   oEvent.getSource().getParent().close();
                        }
            });
           
oValueHelpDialog.addButton(oOkButton);

oValueHelpDialog.open();

Now the Value Help dialog window can be opened and closed.     

As the next step we place the table with two columns Matnr and Descr into the dialog window. We insert this code after the addButton(oOKButton). 

Note: the fields Matnr and Descr must refer to our underlying data model (e.g. provided by the Gateway Service or locally).   

  var oHelpTable = new sap.ui.table.Table({
        selectionMode: sap.ui.table.SelectionMode.Single,
        visibleRowCount: 7,
        width: "300pt"
  });

  oHelpTable.addColumn(
        new sap.ui.table.Column({
                label: new sap.ui.commons.Label({text: "Material Number"}),
                template: new sap.ui.commons.TextView().bindProperty("text", "Matnr"),
                sortProperty: "Matnr",
                filterProperty: "Matnr",
        })
  );

  oHelpTable.addColumn(
        new sap.ui.table.Column({
                label: new sap.ui.commons.Label({text: "Description"}),
                template: new sap.ui.commons.TextView().bindProperty("text", "Descr"),
                sortProperty: "Descr",
                filterProperty: "Descr",
        })
  );

  oValueHelpDialog.addContent(oHelpTable);

Now we can see the dialog window with the empty table:  

In the next step we fetch the data either from a Gateway service or define it locally as a JSON array.

We use the global variable DATABINDING to switch between these two modes – we use true for the Gateway service call and false for the local data binding. 

Insert this line into your main.controller.js function onInit() 

/**
* Called when a controller is instantiated and its View controls (if available) are already created.
* Can be used to modify the View before it is displayed, to bind event handlers and do other one-time
* initialization.
*/
   onInit: function() {
        DATABINDING = false;
   },

Now we continue with the main.view.js and insert before the addContent() line the following code:  

  var oHelpModel = new sap.ui.model.json.JSONModel();
  if (DATABINDING) {
    console.log("Gateway Databinding for Value Help");
// http:///sap/opu/odata/sap//MaterialSet?$select=Matnr,Descr&$format=json
      var helpURL = "http:///sap/opu/odata/sap//MaterialSet";
      var queryString =”$select=Matnr,Descr&$format=json”;
      oHelpModel.loadData( helpURL, queryString, false);
  }
  else {
      console.log("Local Databinding for Value Help");
      oHelpData =
          {"d":{"results":[
                        {"Matnr":"4711","Descr":"Snowboard"},
                        {"Matnr":"4712","Descr":"Mountain Ski"},
                        {"Matnr":"4713","Descr":"Backcountry Ski"},
                        {"Matnr":"4714","Descr":"Freeride Ski"},
                        {"Matnr":"2011001","Descr":"Ski Boots"},
                        {"Matnr":"2011002","Descr":"Ski Poles"},
                        {"Matnr":"2011003","Descr":"Rucksack"},
                        {"Matnr":"5550001","Descr":"Ski Googles"},
                        {"Matnr":"5550002","Descr":"Ski Helmet"},
                        {"Matnr":"5550007","Descr":"GPS Unit"}
      ]}};
      oHelpModel.setData(oHelpData);
  }
           
  oHelpTable.setModel(oHelpModel);
  oHelpTable.bindAggregation("rows", "/d/results");

The structure of the local JSON object is aligned with the Odata Entity Model Structure, so that the same data binding can be used here for local and Gateway data binding.    

Now the dialog window shows up our test data:  

However, the selection is not yet transferred back to the input field. 

For that, we implement the event closed of the ToolPopup control which we already defined but left empty.    

  closed: function (oEvent) {
      // return selected tabled line/value
      var oCore = sap.ui.getCore();
      var oMatnrInput = oCore.byId("idMatnrInput");
      var oContext = oHelpTable.getContextByIndex(oHelpTable.getSelectedIndex());
      if (oContext) {
            var oSel = oContext.getModel().getProperty(oContext.getPath());
            oMatnrInput.setValue(oSel["Matnr"]);
      };
  }

The value of the selected row can be showed now in the input field:

    

Postscriptum

All code samples can be tested within an Eclipse project. Run it in Eclipse as a Web application (we used the Jetty http server plugin for that) and copy the URL into the Chrome Browser. Keep the Jetty window open, and refresh your browser window (F5) to re-run the application. To see the console output, use F12 in the browser to switch to the debugging mode.

References

[1] Entity Data Model (EDM) - http://www.odata.org/documentation/overview#41_Entity_Data_Model_EDM_Overview 

[2] UI5 Blog – Javascript Crash Course for ABAP Developers  http://scn.sap.com/blogs/ui5-for-abap/2013/05/02/javascript-crash-course-for-abap-developers 

About the authors

Vladislav Bezrukov is Development Architect at SAP Consulting focusing on integration technologies, Web and REST Services in ABAP NetWeaver platform (ABAP WS, Gateway). His further professional interests extend to SAP UI5 and HANA technologies, which he is using in his projects in the past couple of years. Email: vladislav.bezrukov@sap.com 

Florian Backfisch is Development Consultant at SAP Consulting. His professional interests are ABAP and UI technologies. Email: florian.backfisch@sap.com 

Johannes Demund is Development Consultant at SAP Consulting. He focuses on ABAP technologies and user interfaces, including NetWeaver Business Client, WebDynpro ABAP, and SAP UI5. Email: johannes.demund@sap.com

Disclaimer

This blog does not represent nor substitute the official SAP documentation. The views expressed by the authors do not necessarily reflect the views of their employer.

14 Comments