本文共 7142 字,大约阅读时间需要 23 分钟。
所谓的单向绑定 (one-way binding),是指 OData model 与 UI 控件之间在数据绑定时, OData model 中数据的变化会同步反应在 UI 控件中,但 UI 控件数据的变化需要手工提交到 OData model;而双向绑定 (two-way binding),则是指 OData model 和 UI 控件的数据双向同步变化。
OData (v2) model 默认的是 one-way binding。OData model 刚开始只支持单向绑定,后来也支持 two-way binding。
使用 one-way 或者 two-way binding,可以进一步简化客户端代码的编写,同时对 CRUD 过程的控制更加精细。但推荐使用 one-way binding。
我们对上一篇程序代码进行修改,先来看看单向绑定。和上一篇比较,代码的变化集中在 App.controller.js 。首先贴出全部代码:
App.controller.js:
sap.ui.define([ "sap/ui/core/mvc/Controller"], function(Controller) { "use strict"; var oModel; var sCurrentPath; var sCurrentEmp; // cureent employee var oEmployeeDialog; return Controller.extend("zui5_odata_sap_backend_crud.controller.App", { onInit: function() { oModel = this.getOwnerComponent().getModel(); oModel.setUseBatch(false); this.getView().setModel(oModel); oEmployeeDialog = this.buildEmpDialog(); }, // Build employee dialog // If not exists, create an instance, otherwise, just get it. buildEmpDialog: function() { var oView = this.getView(); var oEmpDialog = oView.byId("employeeDialog"); if (!oEmpDialog) { oEmpDialog = sap.ui.xmlfragment(oView.getId(), "zui5_odata_sap_backend_crud.view.EmployeeDialog"); oView.addDependent(oEmpDialog); // Attach press event for CancelButton var oCancelButton = oView.byId("CancelButton"); oCancelButton.attachPress(function() { oEmpDialog.close(); }); } return oEmpDialog; }, // onCreate event onCreate: function() { var oView = this.getView(); oEmployeeDialog.open(); oEmployeeDialog.setTitle("Create Employee"); oView.byId("EmpId").setEditable(true); oView.byId("SaveEdit").setVisible(false); oView.byId("SaveCreate").setVisible(true); // clear oView.byId("EmpId").setValue(""); oView.byId("EmpName").setValue(""); oView.byId("EmpAddr").setValue(""); // commit save operation oView.byId("SaveCreate").attachPress(function() { oModel.createEntry("/EmployeeCollection", { properties: { "Mandt": "100", "EmpId": oView.byId("EmpId").getValue(), "EmpName": oView.byId("EmpName").getValue(), "EmpAddr": oView.byId("EmpAddr").getValue() } }); oModel.submitChanges(); sap.m.MessageToast.show("Created Successfully."); // close dialog if (oEmployeeDialog) { oEmployeeDialog.close(); } }); }, onEdit: function() { // no employee was selected if (!sCurrentEmp) { sap.m.MessageToast.show("No Employee was selected."); return; } var oView = this.getView(); oEmployeeDialog.open(); oEmployeeDialog.setTitle("Edit Employee"); oView.byId("EmpId").setEditable(false); oView.byId("SaveEdit").setVisible(true); oView.byId("SaveCreate").setVisible(false); // Attach save event oView.byId("SaveEdit").attachPress(function() { // changes var oChanges = { "EmpName": oView.byId("EmpName").getValue(), "EmpAddr": oView.byId("EmpAddr").getValue() }; oModel.setProperty(sCurrentPath + "/EmpName", oChanges.EmpName); oModel.setProperty(sCurrentPath + "/EmpAddr", oChanges.EmpAddr); if (oModel.hasPendingChanges()) { oModel.submitChanges(); sap.m.MessageToast.show("Changes were saved successfully."); } // close dialog if (oEmployeeDialog) { oEmployeeDialog.close(); } }); }, // onDelete event onDelete: function() { var that = this; // no employee was selected if (!sCurrentEmp) { sap.m.MessageToast.show("No Employee was selected."); return; } var oDeleteDialog = new sap.m.Dialog(); oDeleteDialog.setTitle("Deletion"); var oText = new sap.m.Label({ text: "Are you sure to delete employee [" + sCurrentEmp + "]?" }); oDeleteDialog.addContent(oText); oDeleteDialog.addButton( new sap.m.Button({ text: "Confirm", press: function() { that.deleteEmployee(); oDeleteDialog.close(); } }) ); oDeleteDialog.open(); }, // deletion operation deleteEmployee: function() { oModel.remove(sCurrentPath, { success: function() { sap.m.MessageToast.show("Deletion successful."); }, error: function(oError) { window.console.log("Error", oError); } }); }, onItemPress: function(evt) { var oContext = evt.getSource().getBindingContext(); sCurrentPath = oContext.getPath(); sCurrentEmp = oContext.getProperty("EmpName"); oEmployeeDialog.bindElement(sCurrentPath); } });}); 说明一下主要代码的变化:
单向绑定时,提交编辑的修改通过 setProperty() 方法将变更提交到 OData model,然后用 submitChanges() 方法将变更提交到数据源。如果想取消修改,则使用 resetChanges() 方法:
var oChanges = { "EmpName": oView.byId("EmpName").getValue(), "EmpAddr": oView.byId("EmpAddr").getValue()};oModel.setProperty(sCurrentPath + "/EmpName", oChanges.EmpName);oModel.setProperty(sCurrentPath + "/EmpAddr", oChanges.EmpAddr);if (oModel.hasPendingChanges()) { oModel.submitChanges(); sap.m.MessageToast.show("Changes were saved successfully.");} oModel.hasPendingChanges() 确保有变更才将变更提交到数据源。
新增数据,使用 ODataModel 的 createEntry() 方法,将新增的数据提交到 OData model,然后使用 submitChanges() 方法将请求队列中提交到数据源。如果想取消新增,使用 deleteCreatedEntry() 方法。
oModel.createEntry("/EmployeeCollection", { properties: { "Mandt": "100", "EmpId": oView.byId("EmpId").getValue(), "EmpName": oView.byId("EmpName").getValue(), "EmpAddr": oView.byId("EmpAddr").getValue() }});oModel.submitChanges(); 双向绑定,也涉及到 Edit 及 Create 时候,UI 和 Model 的数据交互。但 UI 和 Model 之间变化自动同步。
1). 在 manifest.json 文件中设置默认的绑定模式:
"sap.ui5": { ... "models": { "i18n": { "type": "sap.ui.model.resource.ResourceModel", "settings": { "bundleName": "zui5_odata_sap_backend_crud.i18n.i18n" } }, "": { "dataSource": "mainService", "type": "sap.ui.model.odata.v2.ODataModel", "settings": { "defaultBindingMode": "TwoWay", "metadataUrlParams": { "sap-documentation": "heading" } } } }, ... } 将 defaultBindingMode 设置为 TwoWay。
2). Edit 不需要使用 setProperty() 方法:
oView.byId("SaveEdit").attachPress(function() { if (oModel.hasPendingChanges()) { oModel.submitChanges(); sap.m.MessageToast.show("Changes were saved successfully."); } // close dialog if (oEmployeeDialog) { oEmployeeDialog.close(); }}); 因为是双向绑定的,UI 中如果有数据变化 oModel.hasPendingChanges() 可以自动获得获取,不需要 setProperty() 。
3). Create 的代码:
oEmployeeDialog.unbindElement();var oContext = oModel.createEntry("/EmployeeCollection", { properties: { "Mandt": "100" }});oEmployeeDialog.setBindingContext(oContext);// commit save operationoView.byId("SaveCreate").attachPress(function() { if (oView.byId("EmpId").getValue()) { oModel.submitChanges(); sap.m.MessageToast.show("Created Successfully."); // close dialog if (oEmployeeDialog) { oEmployeeDialog.close(); } } else { sap.m.MessageToast.show("Employee Id cannot be blank."); }}); 进入 Dialog 的时候,首先解除与已有数据的绑定,然后使用 createEntry() 方法创建一个新的 context。因为 Mandt 字段在 UI 固定为 100,UI 不用管,所以放在 properties 中。设定 oEmpoyeeDialog 的 bindingContext 后,UI 的修改就自动提交给 Model 了。
转载地址:http://upthz.baihongyu.com/