SAPUI5 (29) - 使用 ViewSettingsDialog 实现排序分组和筛选

    xiaoxiao2021-03-25  137

    应用程序的筛选、排序和分组必不可少。为简化开发的工作量,SAPUI5 做了几个通用控件,包括 OpenUI5 的 sap.m.ViewSettingsDialog 和 SAPUI5 的 Smart Filter Toolbar (只在 SAPUI5 中, OpenUI5 中没有)。基本上,sap.m.ViewSettingsDialog 能够满足常规需求。本篇介绍 ViewSettingsDialog 如何帮助在 UI 中实现数据的筛选、排序和分组。

    应用的界面如下:

    当点击这个按钮,弹出对话框。第一个界面是排序,可以按照 Table 的所有字段,进行升序或降序排序。

    点击切换到筛选,我们设置为允许按照【城市】进行筛选:

    点击城市,可以看到涉及的所有城市,允许勾选:

    切换到分组,设置为按【国家】进行分组:

    应用代码的结构:

    index.html

    创建一个 sap.m.App 的实例, App 包含一个 xmlView 的实例:

    <!DOCTYPE HTML> <html> <head> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/> <script src="../resources/sap-ui-core.js" id="sap-ui-bootstrap" data-sap-ui-libs="sap.m" data-sap-ui-xx-bindingSyntax="complex" data-sap-ui-resourceroots='{"webapp": "./"}' data-sap-ui-theme="sap_bluecrystal"> </script> <script> var oApp = new sap.m.App({ pages: [sap.ui.xmlview("appView", "webapp.view.Table")] }); oApp.placeAt("content"); </script> </head> <body class="sapUiBody" role="application"> <div id="content"></div> </body> </html>

    Table.view.xml

    这是一个 View 文件,用于展示界面。View 中包含一个 Table,有【供应商ID】,【供应商名称】,【地址】,【城市】和【国家】五列。绑定到 Suppliers:

    <core:View xmlns:core="sap.ui.core" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" controllerName="webapp.controller.Table" xmlns:html="http://www.w3.org/1999/xhtml"> <Page title="排序,分组和筛选"> <content> <Table items="{/Suppliers}" id="idTable" inset="true"> <headerToolbar> <Toolbar> <Title level="H2" text="供应商清单" /> <ToolbarSpacer /> <Button press="onTableSettings" icon="sap-icon://drop-down-list" /> </Toolbar> </headerToolbar> <columns> <Column id="SupplierID"> <Text text="供应商ID" /> </Column> <Column id="CompanyName"> <Text text="供应商名称" /> </Column> <Column id="Address"> <Text text="地址" /> </Column> <Column id="City"> <Text text="城市" /> </Column> <Column id="Country"> <Text text="国家" /> </Column> </columns> <items> <ColumnListItem > <cells> <ObjectIdentifier title="{SupplierID}" /> <Text text="{CompanyName}" /> <Text text="{Address}" /> <Text text="{City}" /> <Text text="{Country}" /> </cells> </ColumnListItem> </items> </Table> </content> </Page> </core:View>

    SettingsDialog.fragment.xml

    这是一个 OpenUI5 的 Fragement 文件。新建的时候,新建一个文件,然后输入下面的内容。

    <core:FragmentDefinition xmlns:core="sap.ui.core" xmlns="sap.m"> <ViewSettingsDialog confirm="onConfirm"> <sortItems> <ViewSettingsItem selected="true" key="CompanyName" text="供应商名称" /> <ViewSettingsItem key="City" text="城市" /> </sortItems> <groupItems> <ViewSettingsItem key="Country" text="国家"/> </groupItems> <filterItems> <ViewSettingsFilterItem text="城市" key="City"> <items> <ViewSettingsItem key="City" text="Tokyo"/> <ViewSettingsItem key="City" text="London"/> <ViewSettingsItem key="City" text="Manchester"/> </items> </ViewSettingsFilterItem> </filterItems> </ViewSettingsDialog> </core:FragmentDefinition>

    主要是申明一个 sap.m.ViewSettingsDialog, 其中包括 sortItems (排序项),groupItems (分组项) 和 filterItems (筛选项)。对这些些项,我们先用用硬编码的方式,后面再来通用化。比如,现在筛选时,目前界面只出现 Tykyo, London 和 Manchester 三个城市,后面根据 Table 中的数据中涉及的城市,全部出现在筛选项中。

    Table.controller.js

    主要的控制逻辑都在控制器代码中,先给出完整代码:

    sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/model/odata/v2/ODataModel", "sap/ui/model/json/JSONModel", "sap/ui/model/Sorter", "sap/ui/model/Filter"], function (Controller, ODataModel, JSONModel, Sorter, Filter) { "use strict"; return Controller.extend("webapp.controller.Table", { // ------------------------------- // Initialization event // ------------------------------- onInit: function () { // Application model var sServiceUrl = "https://cors-anywhere.herokuapp.com/" + "http://services.odata.org/V3/Northwind/Northwind.svc/"; var oModel = new ODataModel(sServiceUrl); oModel.setUseBatch(false); this.getView().setModel(oModel); }, // --------------------------------------------- // 设置 Table 的 排序,分组和筛选 // --------------------------------------------- onTableSettings: function (oEvent) { var oDialog = this.getView().byId("SettingsDialog"); if (!oDialog) { oDialog = sap.ui.xmlfragment("webapp.view.SettingsDialog", this); } oDialog.open(); }, onConfirm: function (oEvent) { var oBinding = this.getView().byId("idTable").getBinding("items"); var mParams = oEvent.getParameters(); // Apply grouping var aSorters = []; if (mParams.groupItem) { var sGroupKey = mParams.groupItem.getKey(); var bDescending = mParams.groupDescending; aSorters.push(new Sorter(sGroupKey, bDescending, true)); } // Apply sorter if (mParams.sortItem) { var sSortKey = mParams.sortItem.getKey(); var bDescending = mParams.sortDescending; aSorters.push(new Sorter(sSortKey, bDescending)); } oBinding.sort(aSorters); // Apply filters var aFilters = []; if (mParams.filterItems) { var count = mParams.filterItems.length; for (var i = 0; i < count; i++) { var oFilterItem = mParams.filterItems[i]; var oFilter = new Filter(oFilterItem.getKey(), sap.ui.model.FilterOperator.EQ, oFilterItem.getText()); aFilters.push(oFilter); } } oBinding.filter(aFilters); } // end of onConfirm }); });

    代码说明:

    onInit 事件处理函数,实例化 oDataModel 并绑定到服务器端数据,设置当前的 View 所用的 Model 为这个 oDataModel。

    分组:

    var aSorters = []; if (mParams.groupItem) { var sGroupKey = mParams.groupItem.getKey(); var bDescending = mParams.groupDescending; aSorters.push(new Sorter(sGroupKey, bDescending, true)); } var oBinding = this.getView().byId("idTable").getBinding("items"); oBinding.sort(aSorters); 排序: if (mParams.sortItem) { var sSortKey = mParams.sortItem.getKey(); var bDescending = mParams.sortDescending; aSorters.push(new Sorter(sSortKey, bDescending)); } var oBinding = this.getView().byId("idTable").getBinding("items"); oBinding.sort(aSorters); 筛选: var aFilters = []; if (mParams.filterItems) { var count = mParams.filterItems.length; for (var i = 0; i < count; i++) { var oFilterItem = mParams.filterItems[i]; var oFilter = new Filter(oFilterItem.getKey(), sap.ui.model.FilterOperator.EQ, oFilterItem.getText()); aFilters.push(oFilter); } } var oBinding = this.getView().byId("idTable").getBinding("items"); oBinding.filter(aFilters);

    实现按 Table 的所有字段排序

    上面 Controller 对筛选、排序和分组,代码基本上实现了通用的代码。比如通过 var sGroupKey = mParams.groupItem.getKey(); 获取 Group item 的 Key, 通过 var bDescending = mParams.groupDescending; 获取是否按降序排列。 但 Table 中有多个字段,为了实现灵活性,通过代码将所有字段加载到 Sort item 中:

    首先获得 Table 的所有 Headers, 包括 id 和 header text:

    _getColumnHeaders: function(){ var aColumnHeaders = []; var aColumns = this.getView().byId("idTable").getColumns(); for (var i = 0; i < aColumns.length; i++){ var sColumnID = aColumns[i].sId; var sHeaderText = aColumns[i].getHeader().getText();; // ID 中包含 view 的信息,分解得到字段的 id var aID = sColumnID.split('--'); aColumnHeaders.push({ key: aID[1], text: sHeaderText }); } return aColumnHeaders; }

    然后在 onTableSettings() 事件处理程序中将列增加到 Sort Item:

    onTableSettings: function (oEvent) { var oDialog = this.getView().byId("SettingsDialog"); if (!oDialog) { oDialog = sap.ui.xmlfragment("webapp.view.SettingsDialog", this); } // 增加 sort item var aColumnHeaders = this._getColumnHeaders(); oDialog.destroySortItems(); for (var i = 0; i < aColumnHeaders.length; i++){ oDialog.addSortItem(new sap.m.ViewSettingsItem({ key: aColumnHeaders[i].key, text: aColumnHeaders[i].text })); } oDialog.open(); }

    从 Northwind 数据源中加载供应商的城市

    为了实现动态的数据,从 Northwind 数据源中加载数据。使用 JSON Model:

    _getCities: function(){ var aCities = []; //var uniqueCities = []; // 使用 JSON model var sServiceUrl = "http://services.odata.org/V3/Northwind/Northwind.svc/Suppliers"; var oJSONModel = new JSONModel(); oJSONModel.loadData(sServiceUrl, null, false, "GET", false, false, null); var oData = oJSONModel.getProperty("/value"); // 获取城市并且消除重复项 if (oData instanceof Array){ $.each(oData, function(i, element){ if ($.inArray(element.City, aCities) === -1) { aCities.push(element.City); } }); } return aCities.sort(); }

    然后在 onTableSettings 事件处理程序中添加 Filter Item:

    onTableSettings: function (oEvent) { var oDialog = this.getView().byId("SettingsDialog"); if (!oDialog) { oDialog = sap.ui.xmlfragment("webapp.view.SettingsDialog", this); } // 增加 sort item ... // 增加 filter items var aSupplierCities = this._getCities(); var aFilterItems = []; for (var i = 0; i < aSupplierCities.length; i++){ aFilterItems.push( new sap.m.ViewSettingsItem({ text: aSupplierCities[i], key: "City" }) ); } oDialog.destroyFilterItems(); oDialog.addFilterItem(new sap.m.ViewSettingsFilterItem({ key: "Filter_by_City", text: "城市", items: aFilterItems })); oDialog.open(); }

    这样,就实现了动态加载供应商的城市。最后给出 Table.controller.js 重构后的完整代码。

    sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/model/odata/v2/ODataModel", "sap/ui/model/json/JSONModel", "sap/ui/model/Sorter", "sap/ui/model/Filter"], function (Controller, ODataModel, JSONModel, Sorter, Filter) { "use strict"; return Controller.extend("webapp.controller.Table", { // ------------------------------- // Initialization event // ------------------------------- onInit: function () { // Application model var sServiceUrl = "https://cors-anywhere.herokuapp.com/" + "http://services.odata.org/V3/Northwind/Northwind.svc/"; var oModel = new ODataModel(sServiceUrl); oModel.setUseBatch(false); this.getView().setModel(oModel); }, // --------------------------------------------- // 设置 Table 的 排序,分组和筛选 // --------------------------------------------- onTableSettings: function (oEvent) { var oDialog = this.getView().byId("SettingsDialog"); if (!oDialog) { oDialog = sap.ui.xmlfragment("webapp.view.SettingsDialog", this); } // 增加 sort item var aColumnHeaders = this._getColumnHeaders(); oDialog.destroySortItems(); for (var i = 0; i < aColumnHeaders.length; i++) { oDialog.addSortItem(new sap.m.ViewSettingsItem({ key: aColumnHeaders[i].key, text: aColumnHeaders[i].text })); } // 增加 filter items var aSupplierCities = this._getCities(); var aFilterItems = []; for (var i = 0; i < aSupplierCities.length; i++) { aFilterItems.push( new sap.m.ViewSettingsItem({ text: aSupplierCities[i], key: "City" }) ); } oDialog.destroyFilterItems(); oDialog.addFilterItem(new sap.m.ViewSettingsFilterItem({ key: "Filter_by_City", text: "城市", items: aFilterItems })); oDialog.open(); }, onConfirm: function (oEvent) { var oBinding = this.getView().byId("idTable").getBinding("items"); var mParams = oEvent.getParameters(); // Apply grouping var aSorters = []; if (mParams.groupItem) { var sGroupKey = mParams.groupItem.getKey(); var bDescending = mParams.groupDescending; aSorters.push(new Sorter(sGroupKey, bDescending, true)); } // Apply sorter if (mParams.sortItem) { var sSortKey = mParams.sortItem.getKey(); var bDescending = mParams.sortDescending; aSorters.push(new Sorter(sSortKey, bDescending)); } oBinding.sort(aSorters); // Apply filters var aFilters = []; if (mParams.filterItems) { var count = mParams.filterItems.length; for (var i = 0; i < count; i++) { var oFilterItem = mParams.filterItems[i]; var oFilter = new Filter(oFilterItem.getKey(), sap.ui.model.FilterOperator.EQ, oFilterItem.getText()); aFilters.push(oFilter); } } oBinding.filter(aFilters); }, // end of onConfirm _getColumnHeaders: function () { var aColumnHeaders = []; var aColumns = this.getView().byId("idTable").getColumns(); for (var i = 0; i < aColumns.length; i++) { var sColumnID = aColumns[i].sId; var sHeaderText = aColumns[i].getHeader().getText(); // ID 中包含 view 的信息,分解得到字段的 id var aID = sColumnID.split('--'); aColumnHeaders.push({ key: aID[1], text: sHeaderText }); } return aColumnHeaders; }, // end of _getColumnHeaders //----------------------------------------------- // 从 OData 数据服务获取供应商的城市,并且消除重复项 //----------------------------------------------- _getCities: function () { var aCities = []; //var uniqueCities = []; // 使用 JSON model var sServiceUrl = "http://services.odata.org/V3/Northwind/Northwind.svc/Suppliers"; var oJSONModel = new JSONModel(); oJSONModel.loadData(sServiceUrl, null, false, "GET", false, false, null); var oData = oJSONModel.getProperty("/value"); // 获取城市并且消除重复项 if (oData instanceof Array) { $.each(oData, function (i, element) { if ($.inArray(element.City, aCities) === -1) { aCities.push(element.City); } }); } return aCities.sort(); } }); });

    源代码

    29_odata_filter_sort_group_using_viewSettingsDialog

    转载请注明原文地址: https://ju.6miu.com/read-5068.html

    最新回复(0)