I'm facing a problem with sap.ui.table.TreeTable
.
My goal is to develop an SAP Fiori App that displays Tree Data which it receives via an OData V2 Service. For this project I am using the SAP Business Application Studio.
Here's the example I worked with and how I want my app to look like: https://sapui5.hana.ondemand.com/#/entity/sap.ui.table.TreeTable/sample/sap.ui.table.sample.TreeTable.BasicODataTreeBinding
This is what my App looks like right now...
As you can see the TreeTable is filled with the information it gets from my OData service. The problem I'm facing is that it just prints the elements without putting them into hierarchical order.
The "Einzelrollen" element is supposed to be a child of the "Rollen" element, as you can see when looking at the hierarchy-level / nodeid / parentNodeId.
The weird thing about this is, that the Tree-Annotation-Binding seemed to work, since the drillState element functions the way it should be --> the elements below the "Langtext"-element don't have an "expand" option, since they are Leafs.
So why does it not work with the hierarchical annotation elements? Really hope somebody can help me out, looking forward to your guys suggestions! Thanks in advance!
Code below:
View.xml
<mvc:View
controllerName="treetable.controller.tableView"
xmlns:mvc="sap.ui.core.mvc"
displayBlock="true"
xmlns="sap.ui.table"
xmlns:m="sap.m">
<TreeTable
id="treeTable"
selectionMode="Single"
enableColumnReordering="false"
rows="{
path : '/NodeSet',
parameters : {
treeAnnotationProperties : {
hierarchyLevelFor : 'HierarchyLevel',
hierarchyNodeFor : 'NodeId',
hierarchyParentNodeFor : 'ParentNodeID',
hierarchyDrillStateFor : 'DrillState'
}
}
}">
<columns>
<Column label="Description">
<template>
<m:Text text="{Description}" wrapping="false" />
</template>
</Column>
<Column label="HierarchyLevel">
<template>
<m:Text text="{HierarchyLevel}" wrapping="false" />
</template>
</Column>
<Column label="NodeId">
<template>
<m:Text text="{NodeId}" wrapping="false" />
</template>
</Column>
<Column label="ParentNodeID">
<template>
<m:Text text="{ParentNodeID}" wrapping="false" />
</template>
</Column>
</columns>
</TreeTable> </mvc:View>
metadata.xml
<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData">
<edmx:DataServices m:DataServiceVersion="2.0">
<Schema Namespace="Z_ODATA_EXAMPLE_SRV" xml:lang="en" sap:schema-version="1" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityType Name="Node" sap:content-version="1">
<Key>
<PropertyRef Name="NodeId"/>
</Key>
<Property Name="NodeId" Type="Edm.Int32" Nullable="false" sap:unicode="false" sap:label="ID" sap:hierarchy-node-for="NodeId"/>
<Property Name="HierarchyLevel" Type="Edm.Int32" Nullable="false" sap:unicode="false" sap:hierarchy-level-for="NodeId"/>
<Property Name="ParentNodeID" Type="Edm.Int32" sap:unicode="false" sap:hierarchy-parent-node-for="NodeId"/>
<Property Name="DrillState" Type="Edm.String" Nullable="false" MaxLength="8" sap:unicode="false" sap:hierarchy-drill-state-for="NodeId"/>
<Property Name="Description" Type="Edm.String" Nullable="false" MaxLength="80" sap:unicode="false"/>
</EntityType>
<EntityContainer Name="Z_ODATA_EXAMPLE_SRV_Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
<EntitySet Name="NodeSet" EntityType="Z_ODATA_EXAMPLE_SRV.Node" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:content-version="1"/>
</EntityContainer>
<atom:link rel="self" href="https://dae:1234/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
<atom:link rel="latest-version" href="https://dae:1234/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
</Schema>
</edmx:DataServices>
</edmx:Edmx>
manifest.json
{
"_version": "1.32.0",
"sap.app": {
"id": "treetable",
"type": "application",
"i18n": "i18n/i18n.properties",
"applicationVersion": {
"version": "1.0.0"
},
"title": "{{appTitle}}",
"description": "{{appDescription}}",
"resources": "resources.json",
"ach": "ach",
"dataSources": {
"mainService": {
"uri": "/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV",
"type": "OData",
"settings": {
"odataVersion": "2.0",
"localUri": "localService/metadata.xml"
}
}
}
},
"sap.ui": {
"technology": "UI5",
"icons": {
"icon": "sap-icon://task",
"favIcon": "",
"phone": "",
"phone@2": "",
"tablet": "",
"tablet@2": ""
},
"deviceTypes": {
"desktop": true,
"tablet": true,
"phone": true
}
},
"sap.ui5": {
"flexEnabled": false,
"rootView": {
"viewName": "treetable.view.tableView",
"type": "XML",
"async": true,
"id": "tableView"
},
"dependencies": {
"minUI5Version": "1.66.0",
"libs": {
"sap.ui.core": {},
"sap.m": {},
"sap.ui.layout": {},
"sap.ui.table": {}
}
},
"contentDensities": {
"compact": true,
"cozy": true
},
"models": {
"i18n": {
"type": "sap.ui.model.resource.ResourceModel",
"settings": {
"bundleName": "treetable.i18n.i18n"
}
},
"testmodel": {
"type": "sap.ui.model.odata.v2.ODataModel",
"settings": {
"defaultOperationMode": "Server",
"defaultBindingMode": "OneWay",
"defaultCountMode": "Request"
},
"dataSource": "mainService",
"preload": true
}
},
"resources": {
"css": [
{
"uri": "css/style.css"
}
]
},
"routing": {
"config": {
"routerClass": "sap.m.routing.Router",
"viewType": "XML",
"async": true,
"viewPath": "treetable.view",
"controlAggregation": "pages",
"controlId": "app",
"clearControlAggregation": false
},
"routes": [
{
"name": "RoutetableView",
"pattern": "RoutetableView",
"target": ["TargettableView"]
}
],
"targets": {
"TargettableView": {
"viewType": "XML",
"transition": "slide",
"clearControlAggregation": false,
"viewId": "tableView",
"viewName": "tableView"
}
}
}
}
}
view.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/ui/core/UIComponent",
"sap/ui/model/odata/v2/ODataModel",
],
/**
* @param {typeof sap.ui.core.mvc.Controller} Controller
*/
function (Controller) {
"use strict";
return Controller.extend("treetable.controller.tableView", {
onInit: function () {
var oModel = this.getOwnerComponent().getModel("testmodel");
this.getView().setModel(oModel);
var oTreeTable = this.getView().byId("treeTable").setModel(oModel);
oTreeTable.bindRows({
path: "/NodeSet",
parameters : {
treeAnnotationProperties : {
hierarchyLevelFor : 'HierarchyLevel',
hierarchyNodeFor : 'NodeId',
hierarchyParentNodeFor : 'ParentNodeID',
hierarchyDrillStateFor : 'DrillState'} }
});
}
});
});
Your example should work as you expect, i converted it into a running example.
The only thing i change was NodeId
to NodeID
.
But i advice you to remove all this lines. Models which are define in the manifest are propagated automatically:
var oModel = this.getOwnerComponent().getModel("testmodel");
this.getView().setModel(oModel);
var oTreeTable = this.getView().byId("treeTable").setModel(oModel);
Also in the manifest.xml
write "" instead of "testmodel". It is best practise to use the unnamed model for the odata-model.
Bindings are usually created, once the rounter is matching something. Doing it in onInit
is also not best practise. see _onRouteMatched
sap.ui.require([
"sap/ui/core/util/MockServer"
], function(MockServer) {
var oMockServer = new MockServer({
rootUri: "/"
});
// simulate against the metadata and mock data
oMockServer.simulate(`<?xml version="1.0" encoding="utf-8"?>
<edmx:Edmx Version="1.0" xmlns:edmx="http://schemas.microsoft.com/ado/2007/06/edmx" xmlns:m="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns:sap="http://www.sap.com/Protocols/SAPData">
<edmx:DataServices m:DataServiceVersion="2.0">
<Schema Namespace="Z_ODATA_EXAMPLE_SRV" xml:lang="en" sap:schema-version="1" xmlns="http://schemas.microsoft.com/ado/2008/09/edm">
<EntityType Name="Node" sap:content-version="1">
<Key>
<PropertyRef Name="NodeID"/>
</Key>
<Property Name="NodeID" Type="Edm.Int32" Nullable="false" sap:unicode="false" sap:label="ID" sap:hierarchy-node-for="NodeId"/>
<Property Name="HierarchyLevel" Type="Edm.Int32" Nullable="false" sap:unicode="false" sap:hierarchy-level-for="NodeId"/>
<Property Name="ParentNodeID" Type="Edm.Int32" sap:unicode="false" sap:hierarchy-parent-node-for="NodeId"/>
<Property Name="DrillState" Type="Edm.String" Nullable="false" MaxLength="8" sap:unicode="false" sap:hierarchy-drill-state-for="NodeId"/>
<Property Name="Description" Type="Edm.String" Nullable="false" MaxLength="80" sap:unicode="false"/>
</EntityType>
<EntityContainer Name="Z_ODATA_EXAMPLE_SRV_Entities" m:IsDefaultEntityContainer="true" sap:supported-formats="atom json xlsx">
<EntitySet Name="NodeSet" EntityType="Z_ODATA_EXAMPLE_SRV.Node" sap:creatable="false" sap:updatable="false" sap:deletable="false" sap:pageable="false" sap:content-version="1"/>
</EntityContainer>
<atom:link rel="self" href="https://dae:1234/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
<atom:link rel="latest-version" href="https://dae:1234/sap/opu/odata/sap/Z_ODATA_EXAMPLE_SRV/$metadata" xmlns:atom="http://www.w3.org/2005/Atom"/>
</Schema>
</edmx:DataServices>
</edmx:Edmx>`, {
bGenerateMissingMockData: true
});
oMockServer.setEntitySetData("NodeSet", [{
"__metadata": {
"uri": "NodeSet('1')"
},
"NodeID": 1,
"HierarchyLevel": 0,
"Description": "1",
"ParentNodeID": null,
"DrillState": "expanded"
},
{
"__metadata": {
"uri": "NodeSet('2')"
},
"NodeID": 2,
"HierarchyLevel": 0,
"Description": "2",
"ParentNodeID": null,
"DrillState": "expanded"
},
{
"__metadata": {
"uri": "NodeSet('3')"
},
"NodeID": 3,
"HierarchyLevel": 0,
"Description": "3",
"ParentNodeID": null,
"DrillState": "expanded"
},
{
"__metadata": {
"uri": "NodeSet('4')"
},
"NodeID": 4,
"HierarchyLevel": 1,
"Description": "1.1",
"ParentNodeID": 1,
"DrillState": "leaf"
},
{
"__metadata": {
"uri": "NodeSet('5')"
},
"NodeID": 5,
"HierarchyLevel": 1,
"Description": "1.2",
"ParentNodeID": 1,
"DrillState": "expanded"
}
])
// start
oMockServer.start();
const oModel = new sap.ui.model.odata.v2.ODataModel("/");
sap.ui.controller("view1.initial", {
onInit: function(oEvent) {
this.getView().setModel(oModel);
}
});
sap.ui.xmlview("main", {
viewContent: jQuery("#view1").html()
}).placeAt("uiArea");
});
<script id="sap-ui-bootstrap" src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js" data-sap-ui-theme="sap_bluecrystal" data-sap-ui-xx-bindingSyntax="complex" data-sap-ui-compatVersion="edge" data-sap-ui-debug="false" data-sap-ui-libs="sap.m"></script>
<div id="uiArea"></div>
<script id="view1" type="ui5/xmlview">
<mvc:View controllerName="view1.initial" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.ui.table" xmlns:m="sap.m">
<TreeTable id="treeTable" selectionMode="Single" enableColumnReordering="false" rows="{
path : '/NodeSet',
parameters : {
treeAnnotationProperties : {
hierarchyLevelFor : 'HierarchyLevel',
hierarchyNodeFor : 'NodeID',
hierarchyParentNodeFor : 'ParentNodeID',
hierarchyDrillStateFor : 'DrillState'
}
}
}">
<columns>
<Column label="Description">
<template>
<m:Text text="{Description}" wrapping="false" />
</template>
</Column>
<Column label="HierarchyLevel">
<template>
<m:Text text="{HierarchyLevel}" wrapping="false" />
</template>
</Column>
<Column label="NodeId">
<template>
<m:Text text="{NodeID}" wrapping="false" />
</template>
</Column>
<Column label="ParentNodeID">
<template>
<m:Text text="{ParentNodeID}" wrapping="false" />
</template>
</Column>
</columns>
</TreeTable>
</mvc:View>
</script>