SAPUI5 (29) - 使用 ViewSettingsDialog 實現排序分組和篩選


應用程序的篩選、排序和分組必不可少。為簡化開發的工作量,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


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com