本文共 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/