尽管使用层次结构注释,UI5 TreeTable 仍显示平面层次结构

UI5 TreeTable displays flat Hierarchy despite using Hierarchy-Annotations

我遇到了 sap.ui.table.TreeTable 的问题。 我的目标是开发一个 SAP Fiori 应用程序来显示它通过 OData V2 服务接收的树数据。对于这个项目,我使用的是 SAP Business Application Studio。

这是我使用的示例以及我希望我的应用程序的外观:https://sapui5.hana.ondemand.com/#/entity/sap.ui.table.TreeTable/sample/sap.ui.table.sample.TreeTable.BasicODataTreeBinding

这就是我的应用程序现在的样子...

如您所见,TreeTable 中填满了从我的 OData 服务获取的信息。我面临的问题是它只是打印元素,而没有将它们按层次顺序排列。

“Einzelrollen”元素应该是“Rollen”元素的子元素,正如您在查看层次结构级别/nodeid/parentNodeId 时所见。

奇怪的是,Tree-Annotation-Binding 似乎起作用了,因为 drillState 元素按其应有的方式运行 --> “Langtext”元素下面的元素没有“扩展”选项,因为它们是叶子。

那么为什么它不适用于分层注释元素? 真的希望有人能帮助我,期待你们的建议!提前致谢!

代码如下:

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'} }
                });
            }
        });
    });

您的示例应该如您所愿,我将其转换为 运行 示例。

我唯一改变的是 NodeIdNodeID


但是我建议您删除所有这些行。清单中定义的模型会自动传播:

 var oModel = this.getOwnerComponent().getModel("testmodel");
 this.getView().setModel(oModel);

 var oTreeTable = this.getView().byId("treeTable").setModel(oModel);

同样在 manifest.xml 中写“”而不是“testmodel”。最好为 odata-model 使用未命名的模型。


通常会创建绑定,一旦 rounter 匹配了某些东西。在 onInit 中执行此操作也不是最佳做法。见 _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>