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

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值