You can use tree tables on the list report page and the object page in SAP Fiori elements for OData V4.
SAP Fiori elements for OData V4 supports displaying a tree table on the list report page with a draft-enabled service with the following behavior:
-
Only the active entities are displayed.
-
The Editing Status field is not displayed in the filter bar.
-
The draft indicator is shown if a draft exists for an active record.
-
When creating a new object, the new object needs to be saved or discarded.
-
The behavior of already saved objects remains unchanged: a draft can be saved, kept, or discarded. The navigation is also unchanged.
-
Extension points are the same as for the object page.
When switching between edit mode and display mode, the expansion state of a tree table in an object page is not kept.
A tree table cannot be displayed with a draft-enabled service in the flexible column layout.
To enable tree tables on a list report page or an object page, the following parameters are needed in the tableSettings part of the manifest.json:
-
Set the
typetoTreeTable. -
Set the
hierarchyQualifier. You must use the qualifier for theHierarchy.RecursiveHierarchyannotation for the page entity set.
manifest.json"tableSettings": { "type": "TreeTable", "hierarchyQualifier": "NodesHierarchy", ... }
The following creation modes are supported with a tree table:
-
Inline: inline creation mode -
NewPage: create page -
CreationDialog: create dialog
On the list report page, only the create page (default) and the create dialog are supported.
SAP Fiori elements for OData V4 supports the default create mode as well as a custom create mode. To use the custom create mode, add the following annotations to the nodeType section:
-
propertyName: Name of the property on the page entity set used to categorize the node type to be created within the hierarchy. -
values: An object containing the values of thepropertyNameand the corresponding label to be used in the menu:-
value: A value of the property defined by thepropertyNamekey. -
label: The menu item label that can be localized using ani18nkey. -
creationFields: The properties to be displayed when using theCreationDialogmode. ThecreationFieldsparameter can point to aFieldGroupannotation or a comma-separated list of properties.
-
Custom Create Mode Options in the Tree Table
"tableSettings": { "type": "TreeTable", "hierarchyQualifier": "NodesHierarchy", "personalization": true, "creationMode": { "name": "Inline", "nodeType": { "propertyName": "nodeType", "values": { "Zone": "Create a new Zone", "Intermediary": "Create a new Intermediary node", "Line": "Create a new Line item" } }, "isCreateEnabled": ".extension.hierarchy-edit.custom.OPExtend.enableCreate" } }
Custom Create Mode Options in the Tree Table

Set up a create dialog as shown in the following example:
"tableSettings": { "type": "TreeTable", "hierarchyQualifier": "NodesHierarchy", "personalization": true, "creationMode": { "name": "CreationDialog", "creationFields": "Title", "nodeType": { "propertyName": "nodeType", "values": { "Zone": "Create a new Zone", "Intermediary": { "label": "Create a new Intermediary node", "creationFields": "Category",}, "Line": "Create a new Line item" } }, "isCreateEnabled": ".extension.hierarchy-edit.custom.OPExtend.enableCreate" } }
In this example, the create dialog is displayed with the property Title for the node types Zone and Line, and the property Category for the node type Intermediary.
For both the standard create mode and the custom create mode, you can define an isCreateEnabled extension point to control whether the Create button or Create Menu buttons are enabled or disabled. The extension point callback needs to be added to the page controller extension.
The following parameters are provided to the callback:
-
The
valueassociated with the selected menu item.If the standard create mode is used, the
valueisnull. -
The
parent contextof the parent under which the new node is created.If no node is selected (creation at the root level of the hierarchy), the
parent contextisundefined.
manifest.jsonsap.ui.define(["sap/ui/core/mvc/ControllerExtension"], function (ControllerExtension) { "use strict"; return ControllerExtension.extend("hierarchy-edit.custom.OPExtend", { // this section allows to extend lifecycle hooks or override public methods of the base controller //Callback to enable Create actions enableCreate: function (value, parentContext) { switch (parentContext?.getProperty("nodeType")) { case "Zone": return value !== "Zone"; // Anything but 'Zone' under 'Zone' case "Intermediary": return value === "Line"; // Only 'Line' under 'Intermediary' case "Line": return false; // Nothing under 'Line' default: return value === "Zone"; // Only 'Zone' at root level } } } }
The following screenshot shows an example of the outcome. Under an "Intermediary" parent, only a "Line" node type can be created.
Disabled Create Menu Buttons

By default, a newly created node is always displayed as the first child below its parent even if a sort or a filter is applied to the table.
You can use the createInPlace option to place the new node in its real position below its parent, which depends on the sort criteria applied to the table and the back-end server logic. If the new node cannot be visualized due to the filter criteria applied to the table, a message toast is displayed to the user.
In the flexible column layout, when using both the
NewPageandcreateInPlaceoptions of thecreateModeproperty, the new entry is shown (for example, in a subobject page), but no message toast is displayed if it cannot be shown on the object page due to the applied filter criteria.
manifest.json"tableSettings": { "type": "TreeTable", "hierarchyQualifier": "NodesHierarchy", "personalization": true, "creationMode": { "name": "Inline", "createInPlace": true, "nodeType": { "propertyName": "nodeType", "values": { "Zone": "Create a new Zone", "Intermediary": "Create a new Intermediary node", "Line": "Create a new Line item" } }, "isCreateEnabled": ".extension.hierarchy-edit.custom.OPExtend.enableCreate" } }
Drag and drop actions are supported as of SAPUI5 1.124.
Drag and drop between siblings is supported if the ChangeNextSiblingAction term is defined in the RecursiveHierarchyActions annotation. When using the ABAP RESTful Application Programming Model (RAP), this annotation is not set for root entities. For this reason, drag and drop between siblings is not supported on the list report page.
If a node is dropped onto the empty area on the right-hand side of a table, the node is promoted to a root node. In the following example, dropping the "Canada" node onto the highlighted area turns it into a root node, that is, a sibling to the "Europe North" and "America North" nodes.
Dropping a Node onto the Empty Right-Hand Side of a Table

You can use the following extensions to control the behavior of drag and drop:
-
isMoveToPositionAllowed: Define if a source node can be dropped on a specific parent node.-
The associated callback receives the source and target contexts as parameters.
-
When dropping as a root node, the parent node is set to
null.
-
-
isNodeMovable: Define if a node can be dragged.- The associated callback receives the source context as a parameter.
In the following example: drag and drop is enabled.
manifest.json"tableSettings": { "type": "TreeTable", "hierarchyQualifier": "NodesHierarchy", "personalization": true, "creationMode": {...}, "isMoveToPositionAllowed": ".extension.hierarchy-edit.custom.OPExtend.moveToPositionAllowed", "isNodeMovable": ".extension.hierarchy-edit.custom.OPExtend.nodeMovable" }
In the following example: ControllerExtension is used to control the behavior of drag and drop.
manifest.jsonsap.ui.define(["sap/ui/core/mvc/ControllerExtension"], function (ControllerExtension) { "use strict"; return ControllerExtension.extend("hierarchy-edit.custom.OPExtend", { // this section allows to extend lifecycle hooks or override public methods of the base controller //Callback for Drop and Paste actions moveToPositionAllowed: function (sourceContext, parentContext) { switch (parentContext?.getProperty("nodeType")) { case "Zone": return sourceContext?.getProperty("nodeType") === "Intermediary"; //Only 'Intermediary' under a 'Zone' case "Intermediary": return sourceContext?.getProperty("nodeType") === "Line" && sourceContext?.getProperty("name") !== 'Dublin'; // Only 'Line' under 'Intermediary' AND 'Dublin' node cannot be moved case "Line": return false; // Nothing under 'Line' default: return false; } }, //Callback for Drag and Cut actions nodeMovable: function (sourceContext) { return sourceContext?.getProperty("name") !== 'USA'; // 'USA' node cannot be moved or cut } }); });
The following screenshot shows an example of the outcome. The user can drag and drop the "Japan" node under "Asia".
Example of Dropping a Node Under a Parent Node

The following screenshot shows another example of the outcome. Moving the "Dublin" node is forbidden, so the target node is not highlighted.
Example of a Forbidden Move

Users can move a node up or down between its siblings in a tree table. To place a node before its previous sibling or after its next sibling, select the node and choose Move Up or Move Down from the tree table toolbar.
Moving a node up or down is supported if the ChangeNextSiblingAction term is defined in the RecursiveHierarchyActions annotation. When using the ABAP RESTful Application Programming Model (RAP), this annotation is not set for root entities. For this reason, moving up or down a node is not supported on the list report page.
A node that is created without the
createInPlaceoption is displayed as the first child below its parent and is therefore considered "out of place". Move operations are disabled for such nodes. Similarly, moving a node up is disabled if its previous sibling is an "out of place" node.Moving a node up and down is also disabled in the following situations:
A sort is applied to the table.
The
isNodeMovableorisMoveToPositionAllowedextension points returnfalse(see the previous section, Drag and Drop).
Cut and paste actions are supported as of SAPUI5 1.124.
Both actions can be enabled or disabled by using the same extension points as for drag and drop:
-
isNodeMovable: Defines if a node can be cut. -
isMoveToPositionAllowed: Defines if a node can be pasted under a specific parent node.
In the following example, the USA node can't be cut or dragged:
Example of a Node with Disabled Cut Action

When pasting, the position of the pasted node under its parent is defined by the back-end logic, which should reflect the needs of your use case.
Copying a node is supported as of SAPUI5 1.136. It can be enabled or disabled by using the following extension points:
isNodeCopyable: Defines if a node can be copied. The associated callback receives the source context as a parameter.isCopyToPositionAllowed: Defines if a source node can be pasted under a specific parent node. The associated callback receives the source and target contexts as parameters.
manifest.json"tableSettings": { "type": "TreeTable", "hierarchyQualifier": "NodesHierarchy", "personalization": true, "creationMode": {...}, "isNodeCopyable": ".extension.hierarchy-edit.custom.OPExtend.enableCopy", "isCopyToPositionAllowed": ".extension.hierarchy-edit.custom.OPExtend.enablePasteFromCopy" }
You can open the context menu in the tree table by right-clicking on any node within the table. All the other nodes are greyed out. Only bound actions are included in this menu.
Actions that are specific to tree tables, such as cut, paste, expand entire node, or collapse entire node, are not supported with multi-selection.
You can disable drag and drop as well as cut and paste to restrict changes in the hierarchy. To do that, use the UpdateRestrictions and NonUpdatableNavigationProperties annotations on the navigation property to the hierarchy parent.
manifest.json@odata.draft.enabled entity TreeTableSubEntityWithUpdateRestriction { @Core.Immutable: true @Common.Label : 'ID' key ID : String; parent : String; @Common.Label : 'Org level name' name : String; @UI.Hidden : true orgID : String; @Core.Computed : true @UI.Hidden : true DistanceFromRoot : Integer64; Superordinate : Association to TreeTableSubEntityWithUpdateRestriction on Superordinate.ID = parent; Organization : Association to TreeTableEntity on Organization.ID = orgID; } annotate TreeTableSubEntityWithUpdateRestriction with @(Capabilities: {UpdateRestrictions: {NonUpdatableNavigationProperties: [Superordinate]}});
You can prevent users from changing the order of root nodes by using the ChangeSiblingForRootsSupported annotation.
If ChangeSiblingForRootsSupported is set to false, users can't do the following actions:
-
Move a root node up or down
-
Drop a node as a root node between two other root nodes
If no specific restrictions have been set for an action, the following actions are supported:
-
Cutting a root node
-
Pasting a node as a root node
-
Dragging a root node
-
Dropping a node as a root node at the beginning or end of the table or onto the right-hand side of the table
If ChangeSiblingForRootsSupported is not defined, it is considered as set to true.
XML Annotation
<edmx:Reference Uri="/sap/opu/odata/IWFND/CATALOGSERVICE;v=2/Vocabularies(TechnicalName='%2FIWBEP%2FVOC_HIERARCHY',Version='0001',SAP__Origin='LOCAL')/$value"> <edmx:Include Namespace="com.sap.vocabularies.Hierarchy.v1" Alias="SAP__hierarchy"/> </edmx:Reference> <Annotations Target="SAP__self.HierarchyEntityType"> <Annotation Term="SAP__hierarchy.RecursiveHierarchyActions" Qualifier="HierarchyNode"> <Record> <PropertyValue Property="ChangeNextSiblingAction" String="SAP__self.changeNextSibling"/> <PropertyValue Property="CopyAction" String="SAP__self.copy"/> <PropertyValue Property="ChangeSiblingForRootsSupported" Bool="false"/> </Record> </Annotation> </Annotations>
You can use a dedicated TreeTable building block.
-
For more information about this building block, see the API reference.
-
For more information and live examples, see the SAP Fiori development portal at Building Blocks - Table - Tree Table.