Skip to Content
Technical Articles
Author's profile photo Sumit Kumar Kundu

Fiori Elements Tree Table with SAP Annotations

Purpose:

This blog is to show an example of how to show hierarchical data in a tree table by utilizing Fiori Elements (List Report template) using ABAP CDS views.

Example Scenario:

The case at hand is to show a list of purchase orders with their different versions (i.e. revisions) in a Tree table. Different versions of purchase order will be displayed as a subordinate node in a tree table. 

Figure 1 shows the example fiori app: first version (Rev. column value = 0) is the parent node and next versions (Rev. column value > 0)  are the children nodes.

Figure 1 : Purchase Orders app w Hierarchy

 

Preparation:

Like any application built using ABAP programming model for SAP Fiori, the data model has to be finalized before anything else.

The entity data model of the example scenario is depicted in the figure below.

Figure 2 : Entity Data Model depicted

The root entity is based on a consumption CDS view ZCDS_C_USER which has an association to intermediate CDS view ZCDS_I_ORDER_PO_HEADER.

ZCDS_C_USER is to show only the purchase orders the user is entitled to see.

Note: This is just a sample to illustrate the hierarchy annotation approach I have built, the root entity is not mandatory or important here.

The purchase order entity has below properties among others:

Property Use
Id This is the key field of the entity => unique for each node (including parent and child)
ParentId This field will act as a link on the current child entity node to the parent entity node. In other words, this property will hold the value of key field ‘Id’ of the parent entity node
HierLevel This property will hold the depth of the node. In the sample, we are having two levels only but this can be according to your requirement.
For example, 0 => Root node and 1 => Child node
DrillDownState This property will determine whether the node will be expanded or collapsed by default on the UI.
leaf => Collapsed, i.e. the OData service will not fetch the data of children nodes yet
expanded => nodes are expanded on UI and OData will have fetched the data of children nodes

Steps:

  1. CDS view has the business logic to select purchase orders. Among other properties in projection list, CDS view has also the fields stated above. Below is a snippet of CDS view ZCDS_I_ORDER_PO_HEADER:

2. The ABAP CDS entity will be used in OData service. In this case, we have used ‘Reference Data Source’ approach to create the OData service in SEGW because we need to add following ‘sap’ annotations in metadata. Please refer to this blog by Andre Fischer for detailed steps.

3. Next we add following code in the method ‘DEFINE’ of the model provider class (…MPC_EXT)

...

super->define( ).

...

* To create hierarchical CDS
    lr_entity = model->get_entity_type( iv_entity_name = 'ZCDS_I_ORDER_PO_HEADERType' ).
    IF lr_entity IS  BOUND.
      lr_property = lr_entity->get_property( iv_property_name = 'ID' ).
      lr_annotation = lr_property->/iwbep/if_mgw_odata_annotatabl~create_annotation(
                             iv_annotation_namespace =  /iwbep/if_mgw_med_odata_types=>gc_sap_namespace ).
      lr_annotation->add(
          iv_key      = 'hierarchy-node-for' "/IWBEP/IF_ANA_ODATA_TYPES=>GCS_ANA_ODATA_ANNOTATION_KEY–hierarchy_node_for
          iv_value    = 'ID' ).



      lr_property = lr_entity->get_property( iv_property_name = 'HierLevel' ).
      lr_annotation = lr_property->/iwbep/if_mgw_odata_annotatabl~create_annotation(
                             iv_annotation_namespace =  /iwbep/if_mgw_med_odata_types=>gc_sap_namespace ).
      lr_annotation->add(
          iv_key      =  'hierarchy-level-for'"/IWBEP/IF_ANA_ODATA_TYPES=>GCS_ANA_ODATA_ANNOTATION_KEY–hierarchy_node_for
          iv_value    = 'ID' ).


      lr_property = lr_entity->get_property( iv_property_name = 'ParentId'  ).
      lr_annotation = lr_property->/iwbep/if_mgw_odata_annotatabl~create_annotation(
                              iv_annotation_namespace =  /iwbep/if_mgw_med_odata_types=>gc_sap_namespace ).
      lr_annotation->add(
          iv_key      = 'hierarchy-parent-node-for'
          iv_value    = 'ID' ).


      lr_property = lr_entity->get_property( iv_property_name = 'DrillDownState'  ).
      lr_annotation = lr_property->/iwbep/if_mgw_odata_annotatabl~create_annotation(
                              iv_annotation_namespace =  /iwbep/if_mgw_med_odata_types=>gc_sap_namespace ).
      lr_annotation->add(
          iv_key      = 'hierarchy-drill-state-for'
          iv_value    = 'ID' ).

    ENDIF.

For details on sap annotation for OData refer to this page.

5. This will result in a metadata which will like below:

6. Now that OData service is ready, we simply create the UI5 app by using Fiori Elements List Report.

Please follow the following blogs by Jocelyn Dart for detailed steps.

Fiori Elements – How to develop a List Report – Basic Approach

Fiori Elements – How to Develop a List Report – Using Local Annotations

Please set the ‘tableType’ property of list page as ‘TreeTable’ in manifest.json created from the ‘Fiori List Report’ template as shown below.

"sap.ui.generic.app": {
		"_version": "1.3.0",
		"settings": {},
		"pages": {
			"ListReport|ZCDS_I_ORDER_PO_HEADER": {
				"entitySet": "ZCDS_I_ORDER_PO_HEADER",
				"component": {
					"name": "sap.suite.ui.generic.template.ListReport",
					"list": true,
					"settings": {
						"smartVariantManagement": true,
						"tableType": "TreeTable"
					}
				},
....
}

 

Voila! We are done. The UI5 app will recognize the SAP annotations and will render the tree table nicely.

 

Assigned Tags

      20 Comments
      You must be Logged on to comment or reply to a post.
      Author's profile photo Rick Ryan
      Rick Ryan

      Thanks for sharing Sumit

      Author's profile photo Noor Fathima H
      Noor Fathima H

      Hi Sumit,

      Its very nice blog. Can give some more additional drill down details on the creation of tree table through CDs annotation with some sample example like POHeader and POItems displayed as tree structure.

       

      Thanks,

      Fathima

       

      Author's profile photo Lutz Rosenpflanzer
      Lutz Rosenpflanzer

      Hi Sumit,

      I tried the example with E070 (transport request -> task), worked very well - thanks a lot.

      A small remark: In the MPC_>Define I needed to add just one line in the beginning:

      super->define.

      Thanks

      Lutz

      Author's profile photo Sumit Kumar Kundu
      Sumit Kumar Kundu
      Blog Post Author

      Thanks for your feedback. Yes, super->define() was implied. I have included this in the code snippet now explicitly.

      Author's profile photo Paul McFarling
      Paul McFarling

      These are generated via CDS automatically if you use an @Analytics.query: true and a hierarchy methodology.  I can't seem to get all of that working the way I would like. Is there any other way to do this with CDS Annotations or local XML annotations?  I hate messing around in the MPC_EXT class...

      Author's profile photo Sumit Kumar Kundu
      Sumit Kumar Kundu
      Blog Post Author

      This info from SAP help documentation can be a pointer. I haven't tried this myself though. Steps described in this blog post, however, requires the Odata metadata to contain the exact hierarchy annotations as mentioned.

      Regards,

      Sumit

      Author's profile photo Jay Malla
      Jay Malla

      Hi Sumit and Paul - I am working on trying to generate an SAP tree view.  The data I am returning has the NodeID, HierarchyLevel, ParentNodeID, and DrillState - but I am having a challenging time generating the annotations I need.  I don't want to use an MPC class to add the annotations.  Is there a way to do this with CDS annotations?  I tried the recurse and parent/child values - but the annotations are not generating.

      I have created a question at https://answers.sap.com/questions/13192367/sap-cds-how-to-add-hierarchy-annotations-saphierar.html

      If you can take a look, that would be good.

      Thanks,

      Jay

       

      Author's profile photo Gim Han Fu
      Gim Han Fu

      Hi Sumit,

      Very useful and nice blog. Thanks for the sharing.

      Have you try to add a selection/filter to your child node? I have added 2 selection/filter to my parent node and child node however it only worked on the parent node but not the child node.

      @UI.selectionField: [{ position: 10 }]

      Business partner field <–worked when I search for it

      @UI.selectionField: [{ position: 20 }]

      Supplier field <–doesn’t worked when I search for it

      Appreciate you can share with me the solution.

      Thank you.

      Regards,

      Gim Han Fu

      Author's profile photo Sumit Kumar Kundu
      Sumit Kumar Kundu
      Blog Post Author

      Good question! One way to dive deep into this issue is to see, in Network tab of developer's console of your browser, how the filter query is being fired. Do you see any response or any message reported in console?

      I have not tried this myself. But one thing to note is that the drill-down-state determines how much data will be queried at press of 'Go' button. If child node is also to be filtered, it should comply with the OData query filter generated based on drill-down-state by Fiori Elements framework.

      Regards,

      Sumit

      Author's profile photo Gim Han Fu
      Gim Han Fu

      The system always default HIERLEVEL eq '0'

      ?sap-client=110&$filter=HIERLEVEL eq '0' and (COMPANYCODE eq '0001' and HIERLEVEL eq '2') 

      Even though I try to default the HIERLEVEL values to 2, the Hierlevel = 0 still remain the same at the starting point of filter. Hereby I always cannot get the child values.

      Author's profile photo Shamo Mikayilov
      Shamo Mikayilov

      HI Gim,

      did You solved this problem? I have the same problem.

      Thanks in advance

      Best

      Shamo

      Author's profile photo Bhavik Mehta
      Bhavik Mehta

      Hi Sumit,

      Can you let me know what is the parent id passed?

       

      Author's profile photo Sumit Kumar Kundu
      Sumit Kumar Kundu
      Blog Post Author

      In this example used in the blog post, ParentId was derived using below in CDS view:

      concat(POHeader.ebeln, '00000000', POHeader.bsart) as ParentId

      Please note that this example is written using only max two levels of hierarchy, so parent node contains constant value '00000000' in place of PO version to resolve the parentage. In other scenarios, appropriate logic needs to be written for ParentID.

      Best regards,

      Sumit

       

      Author's profile photo Bhavik Mehta
      Bhavik Mehta

      Thanks Sumit!.

      Author's profile photo Mayank Rai
      Mayank Rai

      Facing an issue that since the expand node button of the table tree does not have a name accessibility tool is not able to tell the blind user that there is a expand/collapse node button... Any suggestion if we can give some force name to expand button?

      Author's profile photo Deepesh AG
      Deepesh AG

      Hi Sumit,

      Thanks for the excellent and  informative presentation.

      I followed everything as you explained and got the expected output. But when we set value 'expanded'  for all the parent nodes/header nodes, framework is calling backend service for getting the corresponding children .

      If we have 50 parent node then 50 service calls are going to backed as a batch to get the children by passing ParentNodeID as a filter.

      Is there any way to display all the parent node in collapsed state by default so that I can improve the performance at the time of initial load. User can use the expand button to view the items/children. Please share your comments.

      Thanks,

      Deepesh AG

      Author's profile photo Sumit Kumar Kundu
      Sumit Kumar Kundu
      Blog Post Author

      Hi Deepesh AG ,

      This can be done by implementing appropriate logic for the property which will have annotation.

      sap:hierarchy-drill-state-for

      Please check CDS view code snippet for an example in this blog post. Value leaf in the property signifies collapsed state of the node.

       

      Best regards,

      Sumit

      Author's profile photo Deepesh AG
      Deepesh AG

      Hi Sumit,

       

      Thanks for your reply.

      If we set 'leaf' in DrillDownState against parent node to keep it collapsed, then corresponding children will not display .

      Also the expand button/arrow is not coming if the drill state is 'leaf'.

      Thanks,

      Deepesh AG

      Author's profile photo Sumit Kumar Kundu
      Sumit Kumar Kundu
      Blog Post Author

      Hi Deepesh,

      I meant to use 'leaf' for child nodes as per your requirement. For other issue of expand button not appearing, which UI5 version are you using? I would suggest try to test the behavior with other SAPUI5 versions.

      Best regards,

      Sumit

      Author's profile photo Deepesh AG
      Deepesh AG

      Hi Sumit,

       

      My version is 1.84.7 (202102111006).

      Yes I am using 'leaf' for the child nodes.

      Here framework is making two batch calls to backend ,

      1. Get parent nodes( filter- Hierarchy level = 0 )
      2. Get children - ( filter - ParentNodeID = each parent node fetched from service call 1).

      Second batch call has multiple parts and its happening for every parent nodes. I think this is the reason for the performance issue.

      How can we stop this second batch call which is happening for every parent to get its children? Do we have any annotation to set default state as 'collapsed' ?

       

      Thanks,

      Deepesh AG