这两天研究了一下WEB IDE连接后台数据以及使用本地mockserver进行CRUD操作,连接后台需要对Netweaver进行一些配置,这边就不详细阐述了,直接贴出大神博客的链接,ABAP系列我也不太懂,所以这里不说,我主要说一下在web ide中的见解和配置,这篇博客还会记录image的存储以及使用假数据的CRUD表格操作,附有详细的代码注释,大致上已经看懂了大神们的思路是啥了
web ide配置
根据大神的博客教程,我在这里大致地记录一下要点
WEB IDE连接后台
- 配置web ide安装目录下的识别文件,这个也是和后端连接的标识文件,里面的内容大致是后台的服务器名,标注类型,需要访问服务器的URL等,只要与后端匹配就行,文件名也是,这个文件配置好之后,会对整个workspace中的project生效
- 接着就是进入你自己的项目,配置底层文件,第一个就是neo-app.json,这个文件是配置数据源的文件,开头还声明了项目启动时的第一个看到的欢迎界面,注意这里并不是指代根路由,这个从层级上来讲应该比根路由更高一级,因为从新建项目选项中建立web ide提供的模板时,模板中提供的欢迎界面就是给你四个链接,然后才正式进入app,所以这一块应该是定义初始界面的
- manifest.json文件 这个文件老生常谈了,我们在前面的篇章中介绍过这里面配置过整个项目内部的数据源以及路由配置,相当于项目启动后的入口文件,较为重要,起到了一个声明的作用。在这里我们使用另一种编辑模式descriptor editor,进入data sources标签,点击加号添加并选择识别到的服务器,这里就依赖于我们刚开始的前两项,基于前两项所以我们在这一步就可以识别到服务器的存在
还是刚才的文件,稍微再修改一下其中的model项即可,具体细节就不多说了
PS.在连接到后端服务器之后,metadata.xml文件会自动生成,但是由于配置的原因,po主的mainserver和配置后的服务起到了冲突,我把两者的数据以及metadata文件都删除之后,虽然在控制台中仍然会报错说找不到metadata.xml文件,但是依旧完成了数据的加载,这一点有待商榷,但是在配置文件中删除元数据文件查找项是万万不行的!!!
因为后台大哥工作繁忙,只写了查询语句,所以我就没有试验完整的CRUD操作,有点可惜,不过还有个疑问点就是SAP UI5的遍历,貌似一次性最多只能加载100条,我再考虑是不是要弄个分页啥的,下面贴点截图看看效果
源码我就不上传了,因为基础配置都是公司的服务器,没啥好上传的,自己去上面的博客链接改一下会比较快,下面说说CRUD操作
CRUD
先贴出链接
原作品链接这个是SAP 开发论坛中的项目源码,大神博客中也借鉴了他的源码
博客链接
先贴出文件目录结构以及整体的index.html,因为代码我已经做了非常详细的注释了,我就不在这里一一记录了,最后会说一下大致的思路是什么
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta http-equiv='Content-Type' content='text/html;charset=UTF-8'/>
<!-- Please change the file position of sap-ui-cor.js according to environment -->
<script src="https://openui5.hana.ondemand.com/resources/sap-ui-core.js"
id="sap-ui-bootstrap"
data-sap-ui-libs="sap.m, sap.ui.commons, sap.ui.table"
data-sap-ui-xx-bindingSyntax="complex"
data-sap-ui-theme="sap_bluecrystal">
</script>
<script>
jQuery.sap.require("sap.ui.core.util.MockServer");
var currentUser = null;
var sCurrentPath;
// Application Header
var oAppHeader = new sap.ui.commons.ApplicationHeader("appHeader");
oAppHeader.setLogoSrc("http://sap.github.io/openui5/images/icotxt_white_220x72_blue_open.png");
oAppHeader.setDisplayWelcome(false);
oAppHeader.setDisplayLogoff(false);
oAppHeader.placeAt("content");
// Create mock server
var oMockServer = new sap.ui.core.util.MockServer({
rootUri: "http://mymockserver/",
});
oMockServer.simulate("model/metadata.xml", "model/");
oMockServer.start();
// Application data
var oModel = new sap.ui.model.odata.v2.ODataModel("http://mymockserver/", true);
sap.ui.getCore().setModel(oModel);
//-------------------------------------
// Build a form to edit or create user
// mode: 0 for edting, 1 for creating
//------------------------------------
function buildUserForm(mode){
//首先创建一个弹出框的模板,传递一个参数mode代表状态码 mode: 0 for edting, 1 for creating,用一个content数组表示存入的数据
//依次为标题,邮件,名字,年龄,地址,图片,label为描述,TextField为字段输入框,内置value,定义图片的width,路径
//为什么要加上 formatter 这段代码呢? 原因是因为 Northwind 数据库中图片,前面78个字节是 OLE 相关的信息,
//所以将数据通过 JavaScript 的atob 解码为字符串,截取 78 个字节后面的内容,再使用 btoa 还原为 Base64 编码。
var oSimpleForm = new sap.ui.layout.form.SimpleForm({
content: [
new sap.ui.core.Title({text:"User Information"}),
new sap.ui.commons.Label({text: "Email"}),
new sap.ui.commons.TextField({value: "{Email}", editable: false}),
new sap.ui.commons.Label({text: "First name"}),
new sap.ui.commons.TextField({value: "{Firstname}"}),
new sap.ui.commons.Label({text: "Last name"}),
new sap.ui.commons.TextField({value: "{Lastname}"}),
new sap.ui.commons.Label({text:"Age"}),
new sap.ui.commons.TextField({value: "{Age}"}),
new sap.ui.commons.Label({text:"Address"}),
new sap.ui.commons.TextField({value: "{Address}"}),
new sap.ui.core.Title({text:"Photo"}),
new sap.m.Image({
width: "100px",
src: {
path: "Picture",
formatter: function(sBase64Value){
var sDataUrl = "data:image/bmp;base64," + sBase64Value;
if (sBase64Value){
return sDataUrl;
}else{
return;
}
}
}
})
]
});
// 1 表示新建
if (mode == 1){
var content = oSimpleForm.getContent();
content[2].setEditable(true); //如果是新建状态,调用以上的dialog方法,并且把content数组中第二位改成可编辑状态
}
if (mode == 0){
oSimpleForm.bindElement(sCurrentPath); //如果是可编辑状态,则绑定数据
}
return oSimpleForm; //返回定义完成的简单弹出框表格
}
//----------------------------------------------------
// CREATE Operation
// Form was open when user press [Create user] button
//----------------------------------------------------
function openCreateDialog(){
var oCreateDialog = new sap.ui.commons.Dialog({
minWidth: "400px"
});
oCreateDialog.setTitle("Create User");
var oSimpleForm = buildUserForm(1); // 1 represent creating 状态码 buildUserForm方法中传入mode值进行定义
oCreateDialog.addContent(oSimpleForm);
oCreateDialog.addButton(
new sap.ui.commons.Button({
text: "Submit",
press: function() {
var content = oSimpleForm.getContent(); //当按下提交按钮后得到表单中的所有内容
// new entry
var oEntry = {};
oEntry.Email = content[2].getValue(); //获得定义的content数组中各个输入框中的value
oEntry.Firstname = content[4].getValue();
oEntry.Lastname = content[6].getValue();
oEntry.Age = content[8].getValue();
oEntry.Address = content[10].getValue();
// Commit creating operation
var oModel = sap.ui.getCore().getModel();
oModel.create("/Users", oEntry, { //发送一个create请求,带入设定好的容器oEntry,成功执行回调,反之打印错误
success: function(oData, oResponse){
console.log("Response", oResponse);
oCreateDialog.close(); //关闭弹出框并且刷新整个Model页面
oModel.refresh();
},
error: function(oError){
console.log("Error", oError);
oCreateDialog.close();
}
});
}
})
);
oCreateDialog.open();
};
//-------------------------------------------------
// PUT Operation
// Open dialog when user pressing [Update user' data] button
//-------------------------------------------------
function openUpdateDialog(){
var oUpdateDialog = new sap.ui.commons.Dialog({
minWidth: "600px",
title: "Update user's data"
});
var oSimpleForm = buildUserForm(0);
oUpdateDialog.addContent(oSimpleForm);
oUpdateDialog.addButton(
new sap.ui.commons.Button({
text: "Submit",
press: function() {
var content = oSimpleForm.getContent();
var oEntry = {};
oEntry.Email = content[2].getValue();
oEntry.Firstname = content[4].getValue();
oEntry.Lastname = content[6].getValue();
oEntry.Age = content[8].getValue();
oEntry.Address = content[10].getValue();
oEntry.Picture = "base64_string";
var oModel = sap.ui.getCore().getModel();
var sPath = "/Users('" + oEntry.Email + "')" //获取到路由中原先的email值
oModel.update(sPath, oEntry, {
success: function(oData, oResponse){
console.log("Response", oResponse);
oModel.refresh();
oUpdateDialog.close();
},
error: function(oError){
console.log("Error", oError);
oUpdateDialog.close();
}
});
}
})
);
oUpdateDialog.open();
};
//-----------------------
// DELETE Operation
//-----------------------
function openDeleteDialog(email) {
var oDeleteDialog = new sap.ui.commons.Dialog();
oDeleteDialog.setTitle("Delete User");
var oText = new sap.ui.commons.TextView({text: "Are you sure to delete this user?"}); //确认弹出框
oDeleteDialog.addContent(oText);
oDeleteDialog.addButton(
new sap.ui.commons.Button({
text: "Confirm",
press:function(){
var oModel = sap.ui.getCore().getModel();
oModel.remove("/Users('" + email + "')", { //以email为主键寻找需要删除的条目
success: function(oData, oResponse){
console.log(oResponse);
oModel.refresh();
oDeleteDialog.close();
},
error: function(oError){
console.log("Error", oError);
oDeleteDialog.close();
}
});
}
})
);
oDeleteDialog.open();
}
// Setting up table 创造一个表格,状态为不可编辑,但是使用的组件本身可以更改,但是数据不会变,只是显示层的改动
var oTable = new sap.ui.table.Table({
editable: false,
selectionMode : sap.ui.table.SelectionMode.Single, //单行选择状态
selectionBehavior: sap.ui.table.SelectionBehavior.Row,
rowSelectionChange: function(e) {
var idx = e.getParameter('rowIndex');
if (oTable.isIndexSelected(idx)) {
var cxt = oTable.getContextByIndex(idx);
var path = cxt.sPath;
var obj = oTable.getModel().getProperty(path);
currentUser = obj; //用户信息
sCurrentPath = path; //路径+email作为主键传递
//console.log(path);
}
},
toolbar: new sap.ui.commons.Toolbar({
items: [
new sap.ui.commons.Button({
text: "Create user",
press: function() {
openCreateDialog();
},
}),
new sap.ui.commons.Button({
text: "Update user's data",
press: function() {
var idx = oTable.getSelectedIndex(); //获取选中条数的位置,若为负数代表没有选中,则直接返回不执行以下代码
if (idx == -1) return;
var rows = oTable.getRows();
var user = rows[idx].getCells(); //均获得一个数组
// console.log(user);
openUpdateDialog();
},
}),
new sap.ui.commons.Button({
text: "Delete user",
press: function() {
var idx = oTable.getSelectedIndex();
if (idx == -1) return;
var rows = oTable.getRows();
var user = rows[idx].getCells();
openDeleteDialog(user[0].getValue()); //获取长度为5的数组,选中第一位为email信息,获取到里面的值
},
})
]
}),
});
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "Email"}),
template: new sap.ui.commons.TextField().bindProperty("value", "Email"),
editable: false,
sortProperty: "Email"
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "First name"}),
template: new sap.ui.commons.TextField().bindProperty("value", "Firstname"),
sortProperty: "Firstname",
editable: false,
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "Last name"}),
template: new sap.ui.commons.TextField().bindProperty("value", "Lastname"),
sortProperty: "Lastname",
editable: false,
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "Age"}),
template: new sap.ui.commons.TextField().bindProperty("value", "Age"),
sortProperty: "Age",
editable: false,
}));
oTable.addColumn(new sap.ui.table.Column({
label: new sap.ui.commons.Label({text: "Address"}),
template: new sap.ui.commons.TextField().bindProperty("value", "Address"),
sortProperty: "Address",
editable: false,
}));
oTable.setModel(oModel);
oTable.bindRows("/Users");
oTable.placeAt("content");
</script>
</head>
<body class="sapUiBody" role="application">
<div id="content"></div>
</body>
</html>
大致思路讲解
因为所有的代码全部都集中在了一个html里面,所以我一块块讲,包括metadata的选择以及datasources的设置
- 首先可以看到设置了整个界面的navbar,LOGO以及metadata等配置信息
- 然后是dialog的模板,使用simpleForm组件,因为无论是创建还是修改,用的都是同一个弹出框,所以要先建立这个弹出框的模板用于数据的绑定,在里面存入数据的方式是用到了一个content的数组,长度为10,正好用于存放五个数据以及他们的描述,取出时对应content[x]来判断取了什么
- 传入了一个mode值用于标记,因为在update时并不希望作为主键的email字段有所更改,所以需要一个布尔值去判断触发了哪个按钮的方法从而去让那个输入框更改是否可编辑的状态
- 接着对应的模块就是具体的方法,首先写的是createDialog方法,获取填写在表格中的value值以后通过ui5中的create函数进行提交
- 然后是updateDialog方法,不同的地方在于在执行update函数时,多代入一个参数也就是作为主键标记的email值,这样就可以标识出所修改的项,提交后刷新整个表格
- deleteDialog方法和上一个思路基本相同,不过只需要提供一个email参数去标识需要删除的项即可
- 创建显示的表格,在其中写入方法进行标记具体选中了哪一行
- 在表格上方加入toolbar,放入三个按钮,分别触发三个上面开头写好的三种dialog的方法,并且调用table本身识别标记行的参数,并且传递过去
- 最后,创建具体的数据显示区块,创建表格中的行和列,并且绑定参数,渲染到content中