Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
former_member182670
Contributor

I was trying to use TreeTable control with Odata model binding. Documentation in this area is far from perfect and searching in SDN and internet returned more questions around this topic than answers.

After analyzing source code, unit tests and some intensive debugging sessions I managed to bind TreeTable to Odata model. In this blog I’d like to describe the steps required to achieve it in two different ways: using navigation properties and OData annotations.

Expected result of this example is to have an OData service returning hierarchy data without limitation of depth and simple UI5 application to display the data in TreeTable.


1. Hierarchy using navigation properties

Odata Service

Create new OData service

Create Entity: Node

Add Properties:

Id (key)

  1. Edm.String

Name

  1. Edm.String

ParentId

  1. Edm.String

Create Entity Set: Nodes

Create Association: NodeToParent

Create Navigation Property: ChildNodes

All Artifacts:

Implement NODES_GET_ENTITYSET in DPC_EXT class

METHOD nodeset_get_entityset.
   
DATA: ls_entity LIKE LINE OF et_entityset,
          ls_key   
LIKE LINE OF it_key_tab.

   
CLEAR es_response_context-inlinecount.

* no navigation path - top level call
   
IF lines( it_navigation_path ) = 0.
     
DO 3 TIMES.
        ls_entity
-id = sy-index.
       
CONDENSE ls_entity-id.
        ls_entity
-name = |Node { ls_entity-id }|.
       
APPEND ls_entity TO et_entityset.
     
ENDDO.

      es_response_context-inlinecount
= lines( et_entityset ).
     
RETURN.
   
ENDIF.

   
READ TABLE it_key_tab INTO ls_key INDEX 1.
   
IF strlen( ls_key-value ) > 5. "stop here
     
RETURN.
   
ENDIF.

* this is a call using navigation from parent
* Read key of parent node and return child nodes
   
IF lines( it_navigation_path ) > 0.
     
DO 5 TIMES.
        ls_entity-parentid
= ls_key-value.
        ls_entity
-id = |{ ls_entity-parentid }.{ sy-index }|.
       
CONDENSE ls_entity-id.
        ls_entity
-name = |Node { ls_entity-id }|.
       
APPEND ls_entity TO et_entityset.
     
ENDDO.
      es_response_context-inlinecount
= lines( et_entityset ).
     
RETURN.
   
ENDIF.

 
ENDMETHOD.


UI5 Application


Create UI5 application – index.html


<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8' />


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

<script>
//Create an instance of the table control
var oTable = new sap.ui.table.TreeTable({
columns : [ new sap.ui.table.Column({
label : "Id",
template : "Id"
}), new sap.ui.table.Column({
label : "Name",
template : "Name"
}) ],
selectionMode : sap.ui.table.SelectionMode.Single,
enableColumnReordering : true,
});

//Create a model and bind the table rows to this model


//navigation service
var sServiceUrl = "/sap/opu/odata/sap/ZT38MP_TM_HIER_SRV/";
var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl, { useBatch : true });

oTable.setModel(oModel);

//navigation service binding
oTable.bindRows({
path : "/Nodes",
parameters : {
expand : "ChildNodes",
navigation : {
'Nodes' : 'ChildNodes'
}
}
});


//Bring the table onto the UI
oTable.placeAt("content");
</script>

</head>

<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>

Result:

2. Hierarchy using annotations

We will use following annotations: hierarchy-node-for, hierarchy-level-for, hierarchy-parent-node-for, hierarchy-drill-state-for

List of all  SAP annotations for OData Version 2.0 http://scn.sap.com/docs/DOC-44986

OData service

Create new OData service

Create Entity: Node

Add Properties:

Id (key)

  1. Edm.String

Name

  1. Edm.String

ParentId

  1. Edm.String

Level

  1. Edm.Int32

DrilldownState

  1. Edm.String

Create Entity Set: Nodes

All Artifacts:

Go to Model class (MPC_EXT) and redefine DEFINE method to add annotations:

  METHOD define.
    super
->define( ).

   
DATA:
      lo_annotation  
TYPE REF TO /iwbep/if_mgw_odata_annotation, "#EC NEEDED
      lo_entity_type  TYPE
REF TO /iwbep/if_mgw_odata_entity_typ, "#EC NEEDED
      lo_complex_type
TYPE REF TO /iwbep/if_mgw_odata_cmplx_type, "#EC NEEDED
      lo_property    
TYPE REF TO /iwbep/if_mgw_odata_property, "#EC NEEDED
      lo_entity_set  
TYPE REF TO /iwbep/if_mgw_odata_entity_set. "#EC NEEDED************************************************************************************************************************************   ENTITY - Node***********************************************************************************************************************************
    lo_entity_type
= model->get_entity_type( iv_entity_name = 'Node' ).
************************************************************************************************************************************Properties***********************************************************************************************************************************

    lo_property
= lo_entity_type->get_property( iv_property_name = 'Id' ).
    lo_annotation
= lo_property->/iwbep/if_mgw_odata_annotatabl~create_annotation( iv_annotation_namespace /iwbep/if_mgw_med_odata_types=>gc_sap_namespace ).
    lo_annotation
->add(
        iv_key     
= /iwbep/if_ana_odata_types=>gcs_ana_odata_annotation_key-hierarchy_node_for
        iv_value   
= 'Id' ).

    lo_property
= lo_entity_type->get_property( iv_property_name = 'Level' ).
    lo_annotation
= lo_property->/iwbep/if_mgw_odata_annotatabl~create_annotation( iv_annotation_namespace /iwbep/if_mgw_med_odata_types=>gc_sap_namespace ).
    lo_annotation
->add(
        iv_key     
= /iwbep/if_ana_odata_types=>gcs_ana_odata_annotation_key-hierarchy_level_for
        iv_value   
= 'Id' ).

    lo_property
= lo_entity_type->get_property( iv_property_name = 'ParentId' ).
    lo_annotation
= lo_property->/iwbep/if_mgw_odata_annotatabl~create_annotation( iv_annotation_namespace /iwbep/if_mgw_med_odata_types=>gc_sap_namespace ).
    lo_annotation
->add(
        iv_key     
= /iwbep/if_ana_odata_types=>gcs_ana_odata_annotation_key-hierarchy_parent_node_for
        iv_value   
= 'Id' ).

    lo_property
= lo_entity_type->get_property( iv_property_name = 'DrilldownState' ).
    lo_annotation
= lo_property->/iwbep/if_mgw_odata_annotatabl~create_annotation( iv_annotation_namespace /iwbep/if_mgw_med_odata_types=>gc_sap_namespace ).
    lo_annotation
->add(
        iv_key     
= /iwbep/if_ana_odata_types=>gcs_ana_odata_annotation_key-hierarchy_drill_state_for
        iv_value   
= 'Id' ).
 
ENDMETHOD.

Implement NODES_GET_ENTITYSET

  METHOD nodeset_get_entityset.
   
DATA: ls_filter      LIKE LINE OF it_filter_select_options,
          ls_filter_prop
LIKE LINE OF ls_filter-select_options.
   
DATA: ls_entity LIKE LINE OF et_entityset,
          lv       
LIKE sy-index.

   
CLEAR es_response_context-inlinecount.
   
READ TABLE it_filter_select_options INTO ls_filter WITH KEY property = 'ParentId'.
   
IF sy-subrc = 0.
     
READ TABLE ls_filter-select_options INTO ls_filter_prop INDEX 1.
     
DO 5 TIMES.
        ls_entity-parentid
= ls_filter_prop-low.
        ls_entity
-id = |{ ls_entity-parentid }.{ sy-index }|.
       
CONDENSE ls_entity-id.
        ls_entity
-name = |Node { ls_entity-id }|.
       
IF strlen( ls_entity-id ) > 5. "stop here
          ls_entity-drilldownstate
= 'leaf'.
       
ENDIF.
       
APPEND ls_entity TO et_entityset.
     
ENDDO.
   
ENDIF.

   
READ TABLE it_filter_select_options INTO ls_filter WITH KEY property = 'Level'.

   
IF sy-subrc = 0.
     
READ TABLE ls_filter-select_options INTO ls_filter_prop INDEX 1.
     
IF ls_filter_prop-low = 0.

       
DO 3 TIMES.
          ls_entity
-id = sy-index.
         
CONDENSE ls_entity-id.
          ls_entity
-name = |Node { ls_entity-id }|.
         
APPEND ls_entity TO et_entityset.
       
ENDDO.

        es_response_context-inlinecount
= lines( et_entityset ).
       
RETURN.
     
ENDIF.
   
ENDIF.
 
ENDMETHOD.

UI5 Application

Create UI5 application – index.html


<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8' />


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

<script>
//Create an instance of the table control
var oTable = new sap.ui.table.TreeTable({
columns : [ new sap.ui.table.Column({
label : "Id",
template : "Id"
}), new sap.ui.table.Column({
label : "Name",
template : "Name"
}) ],
selectionMode : sap.ui.table.SelectionMode.Single,
enableColumnReordering : true,
});

//Create a model and bind the table rows to this model

//annotation service
var sServiceUrl = "/sap/opu/odata/sap/ZT38MP_TM_HIER2_SRV_01/";

var oModel = new sap.ui.model.odata.v2.ODataModel(sServiceUrl, { useBatch : true });

oTable.setModel(oModel);

//annotation service binding
oTable.bindRows({
path : "/Nodes",
parameters : {
countMode: "Inline",
numberOfExpandedLevels : 2
}
});

//Bring the table onto the UI
oTable.placeAt("content");
</script>

</head>

<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>

Result:

41 Comments
Labels in this area