Last time I post an article about re-use search help in Fiori. It describe the how to bring the search help meta data from SAP ERP to Fiori. But there are still something unsolved. E.g, really bring the help value data from ERP to Fiori. So today I will show you how to implement a generic F4 help in Fiori. Once you implement it, you can implement a F4 solution just like you use F4 function in ABAP. There is only one odata service to handle all the value help in Fiori. Before we start, let’s look at a real demo screen shot below.

REFX1.JPG

REFX2.JPG

REFX3.JPG

REFX4.JPG

On above screen shot, if you click the company code(first screen shot), the company code’s value help dialog will be appear; the selected value will be back to input field. The third and fourth screen is the same like the first, it shows a dialog of Dunning Area. Both of value help are called the same odata service and the same Fiori dialog box. Actually it can support any kinds of F4 help.

Now let me explain how to do it. Due to odata 2.0, we can’t support the dynamic meta data in odata service. That’s the root cause we have to write lots of odata service to implement kinds of value help in Fiori. But we can solve it even in odata 2.0.(In odata 4.0, we can perfect solve this issue because odata 4.0 will support dynamic meta data). First of all, let’s think about the value help and its look like. Normally it return you a list with several columns, one of the column is the help value you need. Because the columns is not fixed, so we have to find a way to covert the “columns” to “row”. So I defined a simple structure in odata service as a meta data. It looks like below:

types: begin of s_re_f4,

              index   type i,

              f4value type char255,

             end of s_re_f4.


It’s simple but enough to help us. The index is just as a key of odata entry and has no business meaning. The f4value is used to store the actual f4 value data. Here I set the f4 value data as char 255. Because I don’t think in SAP ERP there is a value help data which exceed the length 255.


Let’s use an example to explain how you fill the data with my defined structure.

Now there is value help which contains 3 columns and there are two valid entry like below

company code            description    currency

0001                           SAP DE       Euro

CN00                          SAP China   CNY

For the first entry of internal table with defined structure is the number of columns. On above case, the first row is 3. In the next a few row, you need to fill the column name which will be used by Fiori to display the column text. In our case is Company code, description, currency. After we fill the number of columns and respective column name, we need to fill in the actual f4 value data “cell by cell”, Look at final internal table content. It looks like below


Index f4value
1 3
2 company code
3 description
4 currency
5 0001
6 SAP DE
7 Euro
8 CN00
9 SAP China
10 CNY

In our odata service, we need to return the data like above internal table. Once such kind of data return to Fiori, it’s easy to build a table with given data like above. In our demo, we asked developer to give us 3 parameter from Fiori. They are the table name, field name. Still use above example.

We call generic odata service like this: http://xxxxx.sap.corp/odata/yourservice?search=searchtype,tablename,field

Here we use search to pass the Fiori parameter to odata service, you can use others like filter as you will.

In your odata service, you can write like below

case searchtype.

   when ‘SH’.  “handle search help

   when ‘D’.    “handle domain

 

   when ‘V’.   “handle view

   when ‘T’.    “handle table

endcase.

I paste the SH , just for example.

if iv_search_string is not initial.

           lv_search_string = iv_search_string.

           “split lv_search_string at ‘,’ into lv_f4type lv_tablename lv_fieldname.

           split lv_search_string at ‘,’ into lv_tablename lv_fieldname.

           move lv_tablename to lv_shlpname.

           call function ‘F4IF_GET_SHLP_DESCR’

             exporting

               shlpname = lv_shlpname “Custom Search help

             importing

               shlp     = lv_shlp_top.

           call function ‘F4IF_SELECT_VALUES’

             exporting

               shlp           = lv_shlp_top

               call_shlp_exit = ‘X’

             tables

               recdescr_tab   = lt_recdescr_tab

               return_tab     = lt_retval.

           describe table lt_recdescr_tab lines lv_col_num.

           ls_ref4index = lv_indexkey.

           ls_ref4f4value = lv_col_num.

           lv_indexkey = lv_indexkey + 1.

           append ls_ref4 to lt_ref4.

           loop at lt_recdescr_tab into ls_recdescr_tab.

             ls_ref4index = lv_indexkey.

             ls_ref4f4value = ls_recdescr_tabfieldtext.

             lv_indexkey = lv_indexkey + 1.

             append ls_ref4 to lt_ref4.

           endloop.

           loop at lt_retval into ls_retval.

             ls_ref4index = lv_indexkey.

             ls_ref4f4value = ls_retvalfieldval.

             lv_indexkey = lv_indexkey + 1.

             append ls_ref4 to lt_ref4.

           endloop.

           copy_data_to_ref( exporting is_data = lt_ref4

                                changing  cr_data = er_entityset ).

         endif.

When the odata service back, you just need to build a selecttable to contain those data. It looks like below script.

sap.ui.jsfragment(“REBP.Dialog.SearchHelp”, {

    createContent: function(oController) {

    var oModel = oController.getView().getModel(“REF4”);

    //oModel = new sap.ui.model.odata.ODataModel(that.url,false);

    

  sap.ui.getCore().setModel(oModel);

  //var url = “/REF4Set?search=”+ “REEX_PAYMENT_FI_S” + “,” + “DUNNAREA”;

  var url = “/REF4Set?search=”+ oController.tablename + “,” +oController.field;

  alert(url);

    oModel.read(url, null, null, false,fSuccess,fError);

 

 

    function fSuccess(oData, response){

          searchHelpJson = response.data.results;

       }

    function fError(oEVent){

        alert(“Read Model Failed”);

       }

 

 

    var oDialog = new sap.m.TableSelectDialog({title:”Value Help”,multiSelect:false, confirm: controller.selectF4value, cancel: controller.cancel });

    var objects = searchHelpJson;

    var col_num = Number(objects[0][“F4value”]);

    var oColumnListItem = null;

    for (var i=0; i<col_num; i++){

    var oColumn = new sap.m.Column({hAlign: “Center”});

    var oHead = new sap.m.Text({text: objects[i+1].F4value});

    oColumn.setHeader(oHead);

    oDialog.addColumn(oColumn);

    }

 

    var records_num = ( objects.length – col_num – 1 ) / col_num;

    var index = col_num + 1;

    for (var j=0; j<records_num; j++){

    oColumnListItem = new sap.m.ColumnListItem();

    for (var k = 0; k<col_num; k++){

        var oText = new sap.m.Text({text: objects[index].F4value});

        oColumnListItem.addCell(oText);

        index++;

    }

     oDialog.addItem(oColumnListItem);

 

    }

 

 

    return oDialog;

    },

  

     

});

OK, now you implement a generic F4 help in Fiori. You don’t have to wirte F4 one by one. Just call the same odata service. And there is also generic F4 dialog appear. The whole F4 dialog are created dynamic by given data return from odata service.

Our approach is simple and easy to implement by yourself. I hope it can help you speed up your development in Fiori. If you have concerns or want to know more technical details, see live demo. Just contact me.

Raymond.ni@sap.com


To report this post you need to login first.

5 Comments

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

  1. Matt Harding

    Hi Raymond,

    As someone who has spent way too much time developing Gateway “Search Helps” in recent days, I’m really glad you’ve been thinking about solutions to this problem. However, here’s two concerns for you to have a think about that I would raise:

    1. In my development, many search helps are those types that are dependent on another value; and with dedicated GW services, it’s fairly trivial for a UI developer to get the underlying values via a relationship to the parent entity. With the above approach, there’s quite a bit of logic you’re asking the UI developer to do however – any thoughts on that scenario.

    2. Similarly, isn’t the whole point of Gateway to make the service semantically easy to understand and consume within the UI. e.g. If you want to know about all the Company Codes, wouldn’t you expect to see a CompanyCode entity with all the fields perfectly laid out for you? The above implies an internal knowledge of SAP, and while it would save a lot of effort from the Gateway perspective if you were developing the UI, showing the service to a true Web developer who doesn’t know SAP would have them wondering why…

    But good effort, and nice idea – but for me, it’s a little too close to a search help Web Service without the semantic meaning I believe you should be able to get with Gateway service definitions.

    Cheers,

    Matt

    (0) 
    1. Raymond Ni Post author

      Hello Matt

      Thanks for your reply.

      For the first question, I think you are right. For a pure UI designer or programmer who has little experiences about back-end SAP ERP. S/He is difficult to understand table or fields name. So I think if developer is creating new UI for those old transactions in ERP; then it is easy for them to find table or fields.(Just press F1 and see the technical information). And for those value help which depends on other value help or specific input. My current approach is hard to handle.(Can you mail me some screen shot demo for your case about relationship between two or more value help? Maybe I can find out a way)

      Actually I would expect that SAP can publish some common services for some common entities by area.(Like company code for FIN, cost center, profit center and so on). Because in many transactions, user need to fill those information. I am not sure whether there is “Service Tree”. (I expect there is the service tree in SAP, so before I start to create new service, I can check the service tree first to avoid create similar service again. I heard someone is doing the similar thing or creating a solution, but I don’t know the details)

      Cheers

      Raymond Ni

      (0) 
      1. Matt Harding

        Thanks for your detailed reply Raymond.  In short (rather than email), an example would be Personnel Area and then the search help for Personnel Sub Area which has a composite key including the personnel Area Id. To give you the list of personal sub areas, you would use /PersonnelAreas(‘1000’)/PersonalSubAreas.

        The common services would be nice for sure, though I tend to like pointing a UI person at a single Service entry point and including all required services into that service as an external service which could grow into an unwieldy service if the common service grew too large.

        Lastly, even if the UI person does know SAP well, it’s not a great practice to embed intrinsic SAP specific information into your service, though to hit a deadline, I can fully understand why you would 😉

        Cheers,

        Matt

        (0) 
      2. Maximiliano Colman

        Hi,

        any updates of “And for those value help which depends on other value help or specific input. My current approach is hard to handle.(Can you mail me some screen shot demo for your case about relationship between two or more value help? Maybe I can find out a way)“?

        Regards.

        (0) 
  2. Srdjan Boskovic

    Hi Raymond,

    very good blog, thank you !

    Following Mat’s comment, this approach really helps saving time in prototyping projects, where short deadlines and challenging tasks go hand in hand.

    Thanks and regards,

    srdjan

    (0) 

Leave a Reply