SAPUI5 (24) - 增删改查之查询数据

CRUD是应用程序的核心。openui5是一个前端的UI库,CRUD是通过oData的服务来完成。openui5提交基于http协议的请求给服务器,其它交给服务器端处理。oData协议是微软公司发起,比web service更轻量级的通讯协议。SAP的Neweaver Gateway 就是SAP以OData形式暴露后端业务数据的一个组件。SAPUI5提供的方便的数据绑定功能,将前端展示组件绑定到后端暴露的OData服务上。

使用mock server实现数据查询

目前,我们先使用mock server来模拟服务器端的功能。本次将之前的master-detail程序修改为使用GET请求获取数据并展示。在前一篇起始框架代码的基础上,做如下变更:

  1. 创建master view和master controller
  2. 创建detail view和detail controller
  3. 修改manifest.json, 将空字符串的target设为master

项目文件结构:

[外链图片转存失败(img-3uKoHu0C-1564974244229)(https://raw.githubusercontent.com/stonewm/my_blogs/master/sap_openui5/pics/24/project_files.png)]

创建master view和master controller

Master.view.xml:

<core:View xmlns:core="sap.ui.core" 
           xmlns:mvc="sap.ui.core.mvc" 
           xmlns="sap.m"
			controllerName="stonewang.sapui5.demo.controller.Master" 
			xmlns:html="http://www.w3.org/1999/xhtml">
			
	<Page id="page" title="{i18n>masterViewTitle}">
		<content>
			<Table id="table" width="auto"
				class="sapUiResponsiveMargin"
				items="{/}"
				noDataText="{i18n>tableNoDataText}"
				growing="true"
				growingScrollToLoad="true">
				
				<headerToolbar>
					<Toolbar>
						<Title id="tableHeader" text="Suppliers List"/>
						<ToolbarSpacer />
					</Toolbar>
				</headerToolbar>
				
				<columns>
					<Column id="nameColumn"><header>
						<Text text="{i18n>tableIDColumnTitle}" id="IDColumnTitle"/></header>
					</Column>
					<Column id="unitNumberColumn"><header>
						<Text text="{i18n>tableNameColumnTitle}" id="nameColumnTitle"/></header>
					</Column>
				</columns>
				
				<items>
					<ColumnListItem
						type="Navigation" press="onItemPress">
						<cells>
							<ObjectIdentifier text="{id}"/>
							<ObjectIdentifier text="{Name}"/>
						</cells>
					</ColumnListItem>
				</items>
			</Table>
		
		</content>	
	</Page>

</core:View>

重点说明:

  • 因为Component.js文件中:
var oAppModel = new sap.ui.model.json.JSONModel("/Suppliers");

直接将路径设为/Suppliers,所以上面代码中,master viewsap.m.Tableitems属性设置为{/},是相对于/Suppliers的。这将导致后面我们在表达model中数据的路径时,和之前不同。

Master.controller.js:

sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/ui/core/UIComponent"
    ], 		
		
    function(Controller, UIComponent){
	   "use strict";
	    
	    return Controller.extend("stonewang.sapui5.demo.controller.Master", {

	    	onItemPress: function(oEvent){
	    		var oRouter = UIComponent.getRouterFor(this);
	    		var oItem = oEvent.getSource();
	    		 
	    		var sPath = oItem.getBindingContext().getPath();
	    		oRouter.navTo("detail", {
	    			 supplierPath: encodeURIComponent(sPath)
	    		}, true);
	    	 }
	     });
	
	}
);

和之前的代码相比,没有变化。

创建detail view和detail controller

Detail.view.xml:

<core:View xmlns:core="sap.ui.core" 
		   xmlns:mvc="sap.ui.core.mvc" 
		   xmlns="sap.m"
			controllerName="stonewang.sapui5.demo.controller.Detail" 
			xmlns:html="http://www.w3.org/1999/xhtml">
			
	<Page id="page" showNavButton="true" navButtonPress="onNavPress"
		  title="{i18n>detailTitle}">
		  
		<content>
		  	<ObjectHeader title="{Name}" number="ID: {id}">
				<ObjectAttribute text="{Address/Street}, {Address/City}"/>
			</ObjectHeader>
		</content>
	
	</Page>

</core:View>

Detail.controller.js:

sap.ui.define([
        "sap/ui/core/mvc/Controller",
        "sap/ui/core/UIComponent",
        "sap/ui/core/routing/History"
    ], 		
		
    function(Controller, UIComponent, History){
	   "use strict";
	    
	    return Controller.extend("stonewang.sapui5.demo.controller.Detail", {

	    	// add functions here
	    	onInit: function(){
				var oRouter = UIComponent.getRouterFor(this);
				oRouter.getRoute("detail")
					.attachPatternMatched(this._onObjectMatched, this);	
			},
			
			onNavPress: function() {
				var oHistory = History.getInstance();
				var sPreviousHash = oHistory.getPreviousHash();
				
				if (sPreviousHash != undefined){
					window.history.go(-1);
				}else{
					var oRouter = UIComponent.getRouterFor(this);
					oRouter.navTo("master",{}, true);
				}
			},
			
			_onObjectMatched: function (oEvent) {			
				var sPath = oEvent.getParameter("arguments").supplierPath;
				console.log(decodeURIComponent(sPath));
				this.getView().bindElement({path: decodeURIComponent(sPath)});
			}
	     });	
	}
);

修改manifest.json, 将空字符串的target设为master

修改target,并增加master和detail所映射的view:

"sap.ui5": {
	    ...

			"routes": [
				{
					"pattern": "",
					"name": "master",
					"target": "master"
				},
				{
					"pattern": "detail/{supplierPath}",
					"name": "detail",
					"target": "detail"
				}
			],

			"targets": {
				"master": {
					"viewName": "Master",
					"viewLevel": 1
				},
				"detail": {
					"viewName": "Detail",
					"viewLevel": 2
				},
				"notFound": {
					"viewName": "NotFound",
					"viewId": "notFound"
				}
			}
		}

使用view model

现在我们要在detail view中增加两个按钮,用于直接在页面中导航到上一条和下一条数据。界面如下:

[外链图片转存失败(img-ME4fxNVs-1564974244230)(https://raw.githubusercontent.com/stonewm/my_blogs/master/sap_openui5/pics/24/detailview_add_buttons.png)]

同时,这两个按钮根据当前所在行,enabled属性动态变化,比如当处在第一行,向上就为灰色。view model适合这种动态设定UI元素的状态。方法:

1) 实例化view model

Detail.controller.js文件的onInit事件处理器中实例化view model:

// 创建一个model view, 包含两个button是否enabled的布尔值
var oViewModel = new sap.ui.model.json.JSONModel({
	canGoPrev: false,
	canGoNext: false
});

this.getView().setModel(oViewModel, "viewModel");

2) Detail view中增加按钮

Detail.view.xml文件中增加两个按钮,设置enabled属性:

<subHeader>
	<Toolbar>
		<ToolbarSpacer />
		<Button icon="sap-icon://slim-arrow-up" 
						press="onPageUp" 
						enabled="{viewModel>/canGoPrev}" />
		<Button icon="sap-icon://slim-arrow-down" 
						press="onPageDown" 
						enabled="{viewModel>/canGoNext}" />
	</Toolbar>		
</subHeader>

3) 在detail controller中增加更新状态的代码

Detail.controller.js文件中的_onObjectMatched函数中,定义sObjectID:

this.sObjectID = sPath.substr(sPath.lastIndexOf("/")+1);

因为router的导航是基于路径的,这种方法可以获取最后一个/之后的数字,可以用于知道当前数据所在位置。
比如当处于第一条数据,sObjectID=0,当处于第二条数据,sObjectID=1。

然后再添加一个方法_updateViewModel

_updateViewModel: function(oEvent){
	var oModel = this.getView().getModel();
	var that = this;
	var oViewModel = that.getView().getModel("viewModel");	
	
	var nextObjId = parseInt(that.sObjectID) + 1;
	var prevObjId = parseInt(that.sObjectID) - 1;					

	var bNextEnable = !!oModel.getProperty("/" + nextObjId);
	var bPrevEnable = !!oModel.getProperty("/" + prevObjId);
	
	oViewModel.setProperty("/canGoNext", bNextEnable);
	oViewModel.setProperty("/canGoPrev", bPrevEnable);
	}
 });

代码说明:

  • sObjectId转换成number,加1,使用oModel.getProperty("/" + nextObjId)看看是否存在下一条记录。如果不存在,则表达式为undefinedvar bNextEnable = !!oModel.getProperty("/" + nextObjId);将表达式转换成与之对应的boolean类型。比如表达式为undefined,则!exp为true,!!exp为false

  • 根据这两个值,利用JSONModel.setProperty设置view model的canGoNextcanGoPrev

  • _updateViewModel函数完成,在_onObjectMatched添加调用的语句,_onObjectMatched函数的完整代码如下:

_onObjectMatched: function (oEvent) {		
	// 数据绑定
	var sPath 
		= decodeURIComponent(oEvent.getParameter("arguments").supplierPath);
	this.getView().bindElement({path: sPath});				

	this.sObjectID = sPath.substr(sPath.lastIndexOf("/")+1);
	this._updateViewModel();
}

4) 添加onPageUp和onPageDown处理代码

onPageUp: function(oEvent){				
	var sId = parseInt(this.sObjectID);
	sId = sId - 1;
	
	var oRouter = UIComponent.getRouterFor(this);
	var sNewRoute = encodeURIComponent("/"+sId);
	oRouter.navTo("detail", {supplierPath: sNewRoute});
},

onPageDown: function(oEvent){
	var sId = parseInt(this.sObjectID);
	sId = sId + 1;
	
	var oRouter = UIComponent.getRouterFor(this);				
	var sNewRoute = encodeURIComponent("/"+sId);
	oRouter.navTo("detail", {supplierPath: sNewRoute});
},

切换到其它数据,也是利用routernavTo方法。

源码:

24_zui5_crud_retrieve_v1

24_zui5_crud_retrieve_v2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值