如何搜索sap.m.Tree中的所有节点?

时间:2018-02-20 15:24:30

标签: odata sapui5

我目前正在为我公司的MasterDetail应用程序工作,该应用程序提供表示为节点的可扩展类别。

enter image description here

节点及其子节点与导航属性的绑定不是问题。但是,如果我想在上面的搜索字段中搜索某个组节点,它只会在四个最高节点之间进行过滤。它可以在第一级搜索节点,但如果它们低于第一级,则无法找到节点。

树的绑定:

<Tree
    selectionChange="onSelectionChange"
    id="list"
    noDataText="{masterView>/noDataText}"
    busyIndicatorDelay="{masterView>/delay}"
    items="{path: '/GroupNodes',
                parameters : {
                expand: 'ChildGroupNodes',
                navigation: {
                    'GroupNodes': 'ChildGroupNodes'
                    }
            }
    }">
    <StandardTreeItem 
        title="{Stext}"
        type="Navigation"
        press="onSelectionChange"/>
</Tree>

onSearch:

    onSearch: function(oEvent) {
        if (oEvent.getParameters().refreshButtonPressed) {
            this.onRefresh();
            return;
        }

        var sQuery = oEvent.getParameter("query");
        if (sQuery) {
            this._oListFilterState.aSearch = [new Filter("Stext", FilterOperator.Contains, sQuery)];
        } else {
            this._oListFilterState.aSearch = [];
        }
        this._applyFilterSearch();
    },

_applyFilterSearch:

    _applyFilterSearch: function() {
        var aFilters = this._oListFilterState.aSearch.concat(this._oListFilterState.aFilter),
            oViewModel = this.getModel();

        this._oList.getBinding("items").filter(aFilters, "Application");

        if (aFilters.length !== 0) {
            oViewModel.setProperty("/noDataText", this.getResourceBundle().getText("masterListNoDataWithFilterOrSearchText"));
        } else if (this._oListFilterState.aSearch.length > 0) {
            oViewModel.setProperty("/noDataText", this.getResourceBundle().getText("masterListNoDataText"));
        }
    },

onInit()函数中的Filterstate:

this._oListFilterState = {
    aFilter: [],
    aSearch: []
};

元数据:

<EntityType Name="GroupNode" sap:content-version="1">
      <Key>
         <PropertyRef Name="Grpid"/>
      </Key>
      <Property Name="Grpid" Type="Edm.String" Nullable="false" MaxLength="8" sap:unicode="false" sap:label="Id Trainingsgruppe" sap:creatable="false" sap:updatable="false" sap:filterable="false"/>
      <Property Name="Short" Type="Edm.String" MaxLength="12" sap:unicode="false" sap:label="Kürzel Trainingsgruppe" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
      <Property Name="Stext" Type="Edm.String" MaxLength="40" sap:unicode="false" sap:label="Bezeichnung Trainingsgruppe" sap:creatable="false" sap:updatable="false" sap:filterable="false"/>
      <Property Name="Begda" Type="Edm.DateTime" Precision="0" sap:unicode="false" sap:label="Beginndatum" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
      <Property Name="Endda" Type="Edm.DateTime" Precision="0" sap:unicode="false" sap:label="Endedatum" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
      <Property Name="Level" Type="Edm.Int32" sap:unicode="false" sap:label="Level" sap:creatable="false" sap:updatable="false" sap:sortable="false" sap:filterable="false"/>
      <Property Name="Parentid" Type="Edm.String" Nullable="false" MaxLength="8" sap:unicode="false" sap:label="ParentId" sap:creatable="false" sap:updatable="false" sap:filterable="false"/>
      <NavigationProperty Name="ChildGroupNodes" Relationship="Z_HR_LSO_WORKCENTER_SRV.GroupNodeToParent" FromRole="FromRole_GroupNodeToParent" ToRole="ToRole_GroupNodeToParent"/>
      <NavigationProperty Name="GroupToTrainingType" Relationship="Z_HR_LSO_WORKCENTER_SRV.GroupToTrainingType" FromRole="FromRole_GroupToTrainingType" ToRole="ToRole_GroupToTrainingType"/>
</EntityType>

我们正在使用OData V2,因此无法实现FilterContains.All过滤器。

甚至可以在前端过滤sap.m.Tree的子节点吗?

3 个答案:

答案 0 :(得分:2)

以下是一个工作示例:https://embed.plnkr.co/moTGOT/

首先,通过导航属性is deprecated构建树层次结构。 SAP建议改为使用metadata annotations

  

重要提示:不建议使用导航属性来构建层次结构,建议使用层次结构注释 [...]。

完成向注释方法的迁移后,您可以根据以下条件过滤树客户端

  • ODataModel的operationModedefaultOperationMode的{​​{3}}必须为"Client",如果适用,还需"Auto"
  • 调用ODataTreeBinding时,.filter作为第二个参数传递,需要"Control"

FilterType

对于服务器端过滤,仅支持FilterType "Application"。然后,需要由服务器明确地生成过滤后的树结构。

答案 1 :(得分:0)

我认为这可能与您绑定项目的方式有关,因为我可以使用您的JS在我的示例中过滤子节点。

在进行过滤之前,请检查this._oList.getItems()是否包含其中的所有项目。

我发布了我的代码,因此您可以重建我的项目并了解其工作原理。如果您有更多问题,请与我们联系。




Page.view.xml

  <mvc:View
    controllerName="sap.m.sample.Tree.Page"
    xmlns:mvc="sap.ui.core.mvc"
    xmlns="sap.m">
    <SearchField value="{json>/search}" search="onSearch"/>
        <Tree
            id="Tree"
            items="{path: '/'}">
            <StandardTreeItem title="{text}"/>
        </Tree>
</mvc:View>

Page.controller.js

sap.ui.define(['sap/ui/core/mvc/Controller', 'sap/ui/model/json/JSONModel', 'sap/ui/model/Filter', 'sap/ui/model/FilterOperator'],
function(Controller, JSONModel, Filter, FilterOperator) {
    "use strict";

    var PageController = Controller.extend("sap.m.sample.Tree.Page", {
        onInit: function(evt) {
            // set explored app's demo model on this sample
            var oModel = new JSONModel(jQuery.sap.getModulePath("sap.m.sample.Tree", "/Tree.json"));
            this.getView().setModel(oModel);

            var oJSONModel = new JSONModel();
            this.getView().setModel("json", oJSONModel);

            this._oList = this.byId("Tree");
            this._oListFilterState = {
                aFilter: [],
                aSearch: []
            };
        },

        onSearch: function(oEvent) {
            if (oEvent.getParameters().refreshButtonPressed) {
                this.onRefresh();
                return;
            }

            var sQuery = oEvent.getParameter("query");
            if (sQuery) {
                this._oListFilterState.aSearch = [new Filter("text", FilterOperator.Contains, sQuery)];
            } else {
                this._oListFilterState.aSearch = [];
            }
            this._applyFilterSearch();
        },

        _applyFilterSearch: function() {
            var aFilters = this._oListFilterState.aSearch.concat(this._oListFilterState.aFilter);
                //oViewModel = this.getModel();

            this._oList.getBinding("items").filter(aFilters, "Application");

            // if (aFilters.length !== 0) {
            //  oViewModel.setProperty("/noDataText", this.getResourceBundle().getText("masterListNoDataWithFilterOrSearchText"));
            // } else if (this._oListFilterState.aSearch.length > 0) {
            //  oViewModel.setProperty("/noDataText", this.getResourceBundle().getText("masterListNoDataText"));
            // }
        }

    });

    return PageController;

});

Tree.json

[
{
    "text": "Node1",
    "ref": "sap-icon://attachment-audio",
    "nodes":
    [
        {
            "text": "Node1-1",
            "ref": "sap-icon://attachment-e-pub",
            "nodes":[
                {
                    "text": "Node1-1-1",
                    "ref": "sap-icon://attachment-html"
                },
                {
                    "text": "Node1-1-2",
                    "ref": "sap-icon://attachment-photo",
                    "nodes":[
                        {
                            "text": "Node1-1-2-1",
                            "ref": "sap-icon://attachment-text-file",
                            "nodes":[
                                {
                                    "text": "Node1-1-2-1-1",
                                    "ref": "sap-icon://attachment-video"
                                },
                                {
                                    "text": "Node1-1-2-1-2",
                                    "ref": "sap-icon://attachment-zip-file"
                                },
                                {
                                    "text": "Node1-1-2-1-3",
                                    "ref": "sap-icon://course-program"
                                }
                            ]
                        }
                    ]
                }
            ]
        },
        {
            "text": "Node1-2",
            "ref": "sap-icon://create"
        }
    ]
},
{
    "text": "Node2",
    "ref": "sap-icon://customer-financial-fact-sheet"
}

这就是你所需要的一切,但只是因为你需要这些...... 的index.html

<!DOCTYPE HTML>

<head>
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta charset="utf-8">

    <title>Tree - Basic</title>

    <script id="sap-ui-bootstrap"
        src="https://sapui5.hana.ondemand.com/resources/sap-ui-core.js"
        data-sap-ui-libs="sap.m"
        data-sap-ui-theme="sap_belize"
        data-sap-ui-xx-bindingSyntax="complex"
        data-sap-ui-preload="async"
        data-sap-ui-compatVersion="edge"
        data-sap-ui-resourceroots='{"sap.m.sample.Tree": "./", "sap.ui.demo.mock": "mockdata"}'>
    </script>

    <!-- Application launch configuration -->
    <script>

        sap.ui.getCore().attachInit(function() {
            new sap.m.App ({
                pages: [
                    new sap.m.Page({
                        title: "Tree - Basic",
                        enableScrolling : true,
                        content: [ new sap.ui.core.ComponentContainer({
                            name : "sap.m.sample.Tree"
                        })]
                    })
                ]
            }).placeAt("content");
        });

    </script>
</head>

<!-- UI Content -->
<body class="sapUiBody" id="content" role="application">
</body>

Component.js

sap.ui.define(['sap/ui/core/UIComponent'],
function(UIComponent) {
"use strict";

var Component = UIComponent.extend("sap.m.sample.Tree.Component", {

    metadata : {
        rootView : "sap.m.sample.Tree.Page",
        dependencies : {
            libs : [
                "sap.m",
                "sap.ui.layout"
            ]
        },
        config : {
            sample : {
                files : [
                    "Page.view.xml",
                    "Page.controller.js",
                    "Tree.json"
                ]
            }
        }
    }
});

return Component;

});

答案 2 :(得分:0)

不确定您是否设法解决了问题,但几个月前我确实做了这件事。

在您的控制器中,输入以下功能:

    onSearch: function(oEvent) {

        var searchVal = oEvent.getParameter("newValue");
        var treeFilter = new sap.ui.model.Filter("Text", sap.ui.model.FilterOperator.Contains, searchVal);
        var oBinding = this.getView().byId("tree").mBindingInfos.rows.binding;

        oBinding.filter(treeFilter, FilterType.Application);
        oBinding.expandToLevel(3);
    },

这应该可以立即解决。无论您在搜索框中输入什么内容,它都会使用您的过滤器填充树(最多3个级别,但可以更改)。

onSearch功能当然是在搜索字段的livechange上执行的。