Welcome to Jim's Blog

欢迎欢迎


  • 首页

  • 分类

  • 归档

  • 标签

  • 搜索

Fiori-Traps

发表于 2017-10-20 | | 阅读次数

这里来记录在学习Fiori开发中的一个又一个坑

###coding

日期字段显示

如果不做转换,日期的显示是这样的:

为了看起来‘正常’一点,需要格式化转一下:

1
text="{path: 'model_att>uploadDate', type: 'sap.ui.model.type.Date', formatOptions: { pattern: 'YYYY.MM.dd' }}" active="true"/>

再试试把formatOptions: { pattern: 'YYYY.MM.dd' }省略了看一下
有一个blog可以参考:http://www.furkansonmez.com/sapui5-fiori-how-to-format-odata-time/

View 之间传递数据

View 之间进行数据的传递除了用route之外还可以用model,下面是一个示例:

在Component.js或是Manifest.json文件中定义一个全局JSONModel:

1
2
// create JSON model instance
var jsonModel_share = new sap.ui.model.json.JSONModel();

在发送页面的Controller:

1
2
3
4
5
6
7
8
9
10
11
12
13
// Crate Json Data
var jsonData = {key1:"value1",
key2:"value2",
key3: {key4:"value4",key5:"value5"}
};
// create JSON model instance
var json_send = new sap.ui.model.json.JSONModel();
// set the data for the model
json_send.setData(jsonData);
// set the model to the core
sap.ui.getCore().setModel(json_send, "jsonModel_share");
// nav to another page
this.router.navTo("2ndView");

接收页面的Controller:

1
2
// get data from Global JSON model
var oData = sap.ui.getCore().getModel("jsonModel_share").getData();

splitApp直接打开detail的URI(未解决)

如下图,开发完这个spliApp页面后直接执行没有问题,detail view也打开了第一条数据

但是,如果直接在浏览器中用“http://localhost:53342/webapp/index.html#/detail/300000097”来打开页面,或是这里刷新页面的话,就会是下面的界面

这是哪里出的问题呢?我能想到的是输入地址或是刷新地址”http://localhost:53342/webapp/index.html#/detail/300000097",我们并没有直接处理这个URI patten的逻辑

传输至FLP后,loadData用到的json数据为空

今天做一个demo演示,很简单的效果,就是一个panel下放了一个list,list是自己mock的一些数据,所以直接声明JSONModel,然后loadData,一切正常。几分钟搞定。

数据:

代码1:

传输到FLP后问题出现了,界面只显示label,后面的数据列是空的!很显然是json文件中的数据没有load到model中,怎么办,最笨的办法就是把数据写在contoller里,于是有了下面的代码2:

这样写死了肯定不会有问题,但我的json数据文件就没用了啊,这不行,要找到原因,于是简单google了一下,找到了这个APIjQuery.sap.getModulePath,这个会根据服务的相对路径找到要load的文件路径。正式的生产环境都是要这么用的。于是有了代码3:

setVisible传输至FLP后不好用

这也是个坑!

连接配置

Service can not be reached


WEBIDE在需要和前端Server进行通信时报Service can not be reached,这是因为前端server有一个服务没有激活,下面这个adt服务激活就好了。

发布部署

部署后没有dist文件夹生成

在WEBIDE开发完成以后部署到前端服务器时碰到了这样一个问题。



虽然提示部署成功The application has been deploied in XXX,但目录下却没有dist文件夹出现,解决办法如下:

  1. 新建一个webapp目录,将除neo-app.json之外的文件和文件夹全部剪切到webapp目录下。
  2. 修改neo-app.json的welcomeFile属性值,这里是由’index.html’改为了’webapp/index.html’。
  3. 右键打开project setting,把SAPUI5 Client Build选中。保存后会多了一个Build Configuration的tab配置页。(可以在Build时额外再调整想要增加或是排除的文件。这里不需要做任何操作)

然后重新部署,发现应该出现的dist文件夹出来了:)

dist文件夹下还会自动生成Component-preload.js,这里其实也是一个坑,如果没有这个文件,你的APP一样会报错…

COSR 跨域

这是一个大坑,尤其对于以前没有做过Web开发的我们来说更是灾难。先说一下现有开发环境是怎么解决的。

  1. 如果开发环境是用的eclipse,这个问题很好解决,就是在odata的URI地址前加/proxy/http/ ,eclipse内置的反向代理会自动代理链接服务。
  2. 如果开发环境用的是WEBIDE,这个问题也好解决,就是配Destination,配这个的目的也是配置WEBIDE的反向代理。
  3. 如果,这个如果也是我目前碰到的问题,项目只使用Gateway的Odata服务,简单的BS结构,没有引用SAPUI5的任何库,可以说和SAP没什么问题,只是用它提供的一个REST服务。这时候坑就来了,如果用JSONP,SAP这个声称自己是符合国际标准的Odata服务没有callback参数!不支持callback回调!!坑啊!目前我们用了一个临时的替代方案,使用普通的ajax调用,并且在服务中(sicf)写死用户名和密码。
    1
    2
    3
    4
    5
    6
    7
    $.ajax({
    url: "http://10.212.139.247:8000/sap/opu/odata/sap/ZGJZ_TEST_SRV/ZGJZ_USERSet?$format=json",
    type:'GET',
    success:function(json, textStatus) {
    console.log(json);
    },
    });

Fiori-ODATA-Demo1

发表于 2017-09-21 | 分类于 Fiori | | 阅读次数
  1. READ(Get Entity)
需求 URI
读EntitySet(多条) /sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POHeaderSet
读Entity(单条) /sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POHeaderSet(‘4500000545’)
/sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POItemSet(Ebeln=’4500000364’,Ebelp=’00010’)
加格式 /sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POHeaderSet(‘4500000545’)?$format=json
/sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POHeaderSet(‘4500000545’)?$format=xml
读个别字段(多个) /sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POHeaderSet?$select=Ebeln,Bukrs
读个别字段(单个) /sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POHeaderSet(‘4500000545’)/Lifnr
读个别字段并且加格式 /sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POHeaderSet?$select=Ernam,Bukrs,Ebeln&$format=json
记录数 /sap/opu/odata/sap/ZGJZ_PO_DEMO_SRV/POHeaderSet/$count

上面表格中的URI是不需要在后端进行额外的开发就可以使用的(当然要实现Entity和EntitySet)。可以看出,可以通过’?’来增加查询选项,多个查询选项间用’&’连接。 我们再来看一个这个URI的组成:

URI:

Hello World

发表于 2017-08-31 | | 阅读次数

Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub.

Quick Start

Create a new post

1
$ hexo new "My New Post"

More info: Writing

Run server

1
$ hexo server

More info: Server

Generate static files

1
$ hexo generate

More info: Generating

Deploy to remote sites

1
$ hexo deploy

More info: Deployment

Fiori-Demo1

发表于 2017-08-25 | 分类于 Fiori | | 阅读次数

下面是用WEBIDE开发SAPUI5页面实现一个简单重置ERP用户密码功能,前端又做了一遍,也借此理一下思路。

分析设计


以目标为导向,我们要开发这么一个页面,输入用户名和手机号,或者邮箱,点击提交后,ERP重置密码发送指定的短信或邮箱。我们只做到弹出消息,接下的发送短信和邮件功能不做。

接到这么一个需求,首先想到需求要分为两大部分,前端的页面开发和后端的OData服务(实现密码重置功能)。

前端页面

对于习惯了后端开发的ABAPer来说前端让人无从下手,我是这么做的,因为之前把WalkThrough做了一遍,有了大概的印象,从最简单的HelloWorld只有一个html,到慢慢加入XMLview,再加入Controller,再加入多语言,再加入Component配置文件,再加入Descriptor manifest文件,再加入CSS等等吧,WalkThrough真的是由浅入深的带我们进入到SAPUI的开发,所以我建议像我一样的初学者认真的把这些示例做上n(n>3)遍,对于关键章节,比如View和Controller要一直重复做,直到可以脱离copy、paste,随后就能把框架搭出来,个人认为非常有必要,不啰嗦了,继续。

  • index.html

    新建项目A_DEMO,创建Fileindex.html,敲入一个页面最基本的节点:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    <!DOCTYPE html>
    <html>
    <head>
    <title>ERP秘密重置</title>
    </head>
    <body>
    </body>
    </html>

再加入两个’meta’,这里不有深究

1
2
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="utf-8">

上面很容易理解,然后因为我们要用sapui5开发所以需要加入bootstrap,然后引入我们的View:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<script
id="sap-ui-bootstrap"
src="../../resources/sap-ui-core.js"
data-sap-ui-theme="sap_belize"
data-sap-ui-libs="sap.m"
data-sap-ui-compatVersion="edge"
data-sap-ui-preload="async"
data-sap-ui-resourceroots='{
"sap.ui.demo.wt": "./"
}' >
</script>
<script>
sap.ui.getCore().attachInit(function () {
sap.ui.xmlview({
viewName : "sap.ui.demo.wt.view.App"
}).placeAt("content");
});
</script>

这里我在Fiori-Step4-XML-views里做过介绍,就不再多说了,需要解释一点src="../../resources/sap-ui-core.js",如果src用的是相对路径,那么一定要在项目根目录创建一个项目配置文件’neo-app.json’。
然后我们再加入指定View的代码和把View放到body的代码

1
2
3
4
5
6
7
<script>
sap.ui.getCore().attachInit(function () {
sap.ui.xmlview({
viewName : "sap.ui.demo.wt.view.App"
}).placeAt("content");
});
</script>
1
2
<body class="sapUiBody" id="content">
</body>

至此index.html就已经完成不需要做任何调整了,这里就是指定了我们的运行环境和View文件,接下接就完全由View和Controller文件完全接手了。

  • 创建neo-app.json文件
    详细信息可以参考Create a neo-app.json Project Configuration File,后面OData的配置时我们还要此文件进行配置。

  • 创建’view’文件夹

  • 创建’App.view.xml’

    我们要写一个XMLview,就一定要<mvc:View>做为根节点,然后一定有一个controllerName属性来指定controller文件的路径然,这里就是文件和文件之间的联系,然后加入View所用到的namespace,就是下面的一堆xmlns。

1
2
3
4
5
6
7
8
9
<mvc:View
controllerName="sap.ui.demo.wt.controller.App"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:l="sap.ui.layout"
xmlns:f="sap.ui.layout.form"
xmlns:mvc="sap.ui.core.mvc" >
</mvc:View>



怎么理解这个namespace呢,结合上面的API文档,我们可以看到其实它就是我们要用到的不同的API,冒号和后面的’core’ ‘l’ ‘f’ ‘mvc’又是干吗的呢,比如说我要在View中加一个Label控件,简单一搜API文档就看到这几个库里都有Label,这时就需要加一个前缀,就是namespace来区分,第一个'xmlns="sap.m"后面没有冒号,那它就是老大,就是默认namespace,页面中所有什么都不加直接写标签名的都是用的它下面的控件。


看这一个布局,其实就是一个简单的simpleform控件,上面是title,下面是一个分成两列的form结构。

  • SAPUI5 explored

API中那么多控件我应该选择那一个用,怎么入手呢,不用急,SAP提供了很好的参考示例,并且都附有模版代码,我们只需要像逛超市一样选择相中的样式copy过来改改就可以。

打开后可以根据需要进行过滤筛选,也可以在进而进行search

既然来选择布局的,那我就输入layout来进行搜索咯,然后会出现好多layout供我们选择。

下面这个布局很面熟吧,就它了

点击右上角查看源码,找到想要的部分copy下来或者可以整个下载下来慢慢试,下面我想要的部分:


OK,拷过来就可以开始改了,不会?没关系,SAP又提供了API的具体用法,参考API reference


这里就可以看到有两个Module都有这个SimpleForm控件,所以我们要用:f来加以区分。这里对每一个属性的用法都有做介绍,非常详细。
改完以后的代码就是下面这样了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<mvc:View
controllerName="sap.ui.demo.wt.controller.App"
xmlns="sap.m"
xmlns:core="sap.ui.core"
xmlns:l="sap.ui.layout"
xmlns:f="sap.ui.layout.form"
xmlns:mvc="sap.ui.core.mvc" >
<f:SimpleForm id="SimpleForm1" layout="ResponsiveGridLayout"
title="ERP系统-用户密码自主重置"
labelSpanXL="4" labelSpanL="4" labelSpanM="12" labelSpanS="12" adjustLabelSpan="false"
emptySpanXL="0" emptySpanL="0" emptySpanM="0" emptySpanS="0" columnsXL="2" columnsL="2" columnsM="2" singleContainerFullSize="false">
<f:content>
<core:Title text="信息输入"/>
<Label text="用户帐号" width="100%" id="__label0"/>
<Input width="50%" valueLiveUpdate="true" id="UserId"/>
<Label text="手机号" width="100%" id="__label1"/>
<Input width="50%" valueLiveUpdate="true" id="UserTel"/>
<Label text="邮箱" width="100%" id="__label2"/>
<Input width="50%" id="UserMail"/>
<Label/>
<Button text="提交" width="100px" id="__button0" press="onSubmit"/>
<core:Title text="输入说明"/>
<Text text="1.邮箱和移动电话任意输入一项即可;\n 2.两项都输入时,先验证邮箱,后验证移动电话,只要有一项和ERP系统用户信息中维护的一致即可;\n 3.有任何建议或意见,请发邮件到:basis@shenhua.cc" id="__text0"/>
</f:content>
</f:SimpleForm>
</mvc:View>

OK至此,view也做完了,剩下的就是controller了。

  • 新建controller文件夹和App.controller.js文件

    速度太慢了,加快速度!contrller的写法我在之前的帖子上也做了详细说明了,就不再赘述了,看注释来理解吧,很简单,最关键的就是callFucntion来调用ODATA服务和成功后的处理。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
sap.ui.define(["sap/ui/core/mvc/Controller", "sap/ui/model/json/JSONModel"], function(Controller, JSONModel) {
"use strict";
return Controller.extend("sap.ui.demo.wt.controller.App", {
// 按钮事件
onSubmit: function() {
//定义三个变量来取屏幕上三个Input控件输入的值
var UserId = this.getView().byId("UserId").getValue();
var UserTel = this.getView().byId("UserTel").getValue();
var UserMail = this.getView().byId("UserMail").getValue();
//定义OModel,并指定OModel路径
var oModel = new sap.ui.model.odata.ODataModel("/sap/opu/odata/sap/ZGJZ_PWD_RESET_SRV/");
//绑定oModel到view上
this.getView().setModel(oModel);
//Function import的参数
var urlParameters = {
"userMail": UserMail,
"userTel": UserTel,
"userId": UserId
};
//Call ODATA
oModel.callFunction("/ZGJZ_PWD_RESET", {
method: "GET", //Default "GET"
urlParameters: urlParameters, //Function import的参数
//ODATA访问成功的话执行下面的处理
success: function(oData, response) {
// var aa = oData.results.length;
var resType = oData.Type;
var resMsg = oData.Msg;
var resPwd = oData.Pwd;
if (resType == "S") {
sap.m.MessageToast.show(resMsg + resPwd);
} else if (resType == "F") {
sap.m.MessageToast.show(resMsg);
}
},
//ODATA访问失败的话执行下面的处理
error: function(error) {
sap.m.MessageToast.show("Server Connection Aborted");
}
});
}
});
});


这里最关键的就是这个callFunction了,两个参数,第一个是要调的function名字,第二个是{}引起来的一个map, 其中又可以有多个参数,比如method,这里写了GET,默认也是GET,所以可以省略,最最重要的就是后面的两个,success和error,这是两个返回函数,分别是ODATA执行成功时和失败时执行的过程,所以我们要写的逻辑也就在这个里面。success: function(oData, response) 和error: function(error)可以理解成固定写法,执行ODATA后所有的返回值都是在这里面,debug打开找吧,这个例子中返回值是一个entity所以直接用oData.属性值就能访问,如果是entityset,就要for循环出来一一处理了。

后端ODATA开发

  • SE11 创建结构

    这里主要是为了方便后面用import的方式建entity,不建结构也可以
  • SEGW 创建Project

import创建entity(如果Import DDIC遇到下拉列表为空的情况,用en语言重新登录GUI即可)

说一下的是这些字段Creatable/Updatable/Sortable/..等这些flag,它们的作用就是在生成metadata时告诉oData的使用者,哪些字段可以做Sort,哪些不为空,这里的设置并不会影响功能。

建了entity以后同样在Data Model那里右键创建一个Function import,



注意我这里Return的是一个Entity,并没有返回EntitySet,意思就是返回的是一行数据或者说一个结构,不是内表。HTTP要用GET。

建完以后生成然后进行到EXT中进行方法的redefine

在这个类中找到EXECUTE_ACTION方法,右键redefine

下面是实现的代码,ABAP的内容就不介绍了,时间仓促,写的也是最简单的代码,不考虑效率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
method /IWBEP/IF_MGW_APPL_SRV_RUNTIME~EXECUTE_ACTION.
DATA: ls_parameter TYPE /iwbep/s_mgw_name_value_pair,
lt_userinfo TYPE TABLE OF zuserinfo,
ls_PWD TYPE ZGJZ_PWD,
ls_entity TYPE ZCL_ZGJZ_PWD_RESET_MPC=>TS_REPMSG.
TYPES: BEGIN OF ty_input,
userMail(30),
userTel(11),
userId(20),
END OF ty_input.
data ls_input type ty_input.
data l_pass.
data l_pwd_randow type string.
data l_pwd_new type XUNCODE.
data l_XUBNAME type XUBNAME.
DATA LT_PWD TYPE /GRCPI/GRIA_T_PASWDRESTDATA.
DEFINE return_msg.
ls_entity-type = &1.
ls_entity-msg = &2.
ls_entity-pwd = &3.
copy_data_to_ref( EXPORTING is_data = ls_entity
CHANGING cr_data = er_data ).
end-OF-DEFINITION.
IF iv_action_name = 'ZGJZ_PWD_RESET'. " Check what action is being requested
IF it_parameter IS NOT INITIAL.
* Read Function import parameter value
READ TABLE it_parameter INTO ls_parameter WITH KEY name ='userId'.
IF sy-subrc = 0.
ls_input-userId = ls_parameter-value.
ENDIF.
READ TABLE it_parameter INTO ls_parameter WITH KEY name ='userTel'.
IF sy-subrc = 0.
ls_input-userTel = ls_parameter-value.
ENDIF.
READ TABLE it_parameter INTO ls_parameter WITH KEY name ='userMail'.
IF sy-subrc = 0.
ls_input-userMail = ls_parameter-value.
ENDIF.
* get user detail via BAPI
DATA LS_USERNAME TYPE BAPIBNAME-BAPIBNAME.
DATA LT_RETURN TYPE TABLE OF BAPIRET2.
DATA LT_ADDTEL TYPE TABLE OF BAPIADTEL.
DATA LT_ADDSMTP TYPE TABLE OF BAPIADSMTP.
DATA LS_RETURN like LINE OF LT_RETURN.
DATA LS_ADDTEL like LINE OF LT_ADDTEL.
DATA LS_ADDSMTP like LINE OF LT_ADDSMTP.
LS_USERNAME = ls_input-userId.
CALL FUNCTION 'BAPI_USER_GET_DETAIL'
EXPORTING
USERNAME = LS_USERNAME
TABLES
RETURN = LT_RETURN
ADDTEL = LT_ADDTEL
ADDSMTP = LT_ADDSMTP.
IF SY-SUBRC = 0.
READ TABLE lt_return INTO LS_RETURN with key TYPE = 'E'.
IF sy-subrc = 0.
return_msg 'F' LS_RETURN-message ''.
RETURN.
ENDIF.
LOOP AT LT_ADDSMTP INTO LS_ADDSMTP.
TRANSLATE LS_ADDSMTP-E_MAIL TO UPPER CASE.
TRANSLATE ls_input-userMail TO UPPER CASE.
IF LS_ADDSMTP-E_MAIL = ls_input-userMail.
l_pass = 'X'.
exit.
ENDIF.
ENDLOOP.
LOOP AT LT_ADDTEL INTO LS_ADDTEL.
IF LS_ADDTEL-telephone = ls_input-userTel.
l_pass = 'X'.
exit.
ENDIF.
ENDLOOP.
IF l_pass = 'X'.
*GENERAL_GET_RANDOM_PWD 生成随机密码
CALL FUNCTION 'GENERAL_GET_RANDOM_PWD'
EXPORTING
NUMBER_CHARS = 8
IMPORTING
RANDOM_PWD = l_pwd_randow
.
l_pwd_new = l_pwd_randow.
l_XUBNAME = ls_username.
CALL FUNCTION '/GRCPI/GRIA_USER_RESET_PWD'
EXPORTING
IV_USERID = l_XUBNAME
IV_PASSWORD_NEW = l_pwd_new
* IV_SYNCHONIZE =
* IV_VERIFICATION_SYSTEM =
* IMPORTING
* EV_PASSWORD =
* EV_EMAIL =
* EV_RETURN_CODE =
* ET_MESSAGE =
TABLES
ET_USRPSWDDATA = LT_PWD
.
return_msg 'S' '密码重设成功,初始密码为:' l_pwd_new.
*/GRCPI/GRIA_USER_RESET_PWD 重设密码
ELSE.
return_msg 'F' '邮箱和手机号验证失败' ''.
ENDIF.
ELSE.
return_msg 'F' 'BAPI执行失败' ''.
ENDIF.
ENDIF.
ENDIF.
endmethod.

  • 注册服务

    注册此服务到前端。

    点击Maintain进行Gateway Server,然后打开Gateway Client进行测试



/sap/opu/odata/sap/ZGJZ_PWD_RESET_SRV/$metadata 查看 metadata

/sap/opu/odata/sap/ZGJZ_PWD_RESET_SRV/ZGJZ_PWD_RESET?userMail='aaa@lg.com'&userTel='15801615353'&userId='ZZGUOJZ'直接对我们的函数进行测试,注意多个参数的先后顺序和大小写,中间用’&’分开。可以看出’?’后的部分’userMail=’aaa@lg.com’&userTel=’15801615353’&userId=’ZZGUOJZ’’就是我们在前端页面中需要传入的参数

  • 后端debug
    执行,此时如果我们在实现的方法中加了外部断点,就可以debug到方法中,注意这里如果停的时候过长,整个请求会connection time out

    这里看一下这些传入参数的值:


    我们最终的输出就在这里,不论是返回的结构(Entity)还是内表(EntitySet),只要填充到这里就可以。

    下面就可以看到服务的返回值了:

OK。接下来我们就要到前端去验证使用这个ODATA服务了

  • 前端debug
    执行我们开发的前端页面,如果用的是chrome浏览器,点击F12进行控制台,在resource中找到我们要debug的controller,代码前加入断点。

    在前端页面输入对应的值后点击按钮“提交”就会自动运行至断点,在这里我们可以查看相应的变量有没有正确赋值。更详细的debug方法可以百度jsdebug,基本都是类似的。

忘了一个重要的内容,以上执行是不能成功的,因为没有连接后端的配置,我一开始也是做到这里,但执行时发现ODATA服务并不是连的后端的域名,而是locaohost:xxxx,原因就是在neo-app.json文件中需要增加后台服务器的配置信息。
完整的neo-app.json文件应该是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
{
"welcomeFile": "/index.html",
"routes": [
{
"path": "/resources",
"target": {
"type": "service",
"name": "sapui5",
"entryPath": "/resources"
},
"description": "SAPUI5 Resources"
},
{
"path": "/sap/opu/odata",
"target": {
"type": "destination",
"name": "N74",
"entryPath": "/sap/opu/odata"
},
"description": "N74"
},
{
"path": "/test-resources",
"target": {
"type": "service",
"name": "sapui5",
"entryPath": "/test-resources"
},
"description": "SAPUI5 Test Resources"
}
],
"sendWelcomeFileRedirect": true
}

完整代码:http://pan.baidu.com/s/1bpgwAqN 不用谢

结构转化

加入component

上面的示例非常简单,基本实现了需求,但文件结构有点简单,往FLP中迁移的话结构需要再做调整,我们下面就继续按tutorials中文件结构一步步调整它。

  1. 加入component容器
    这里首先要修改index.html,修改<script>标签,加入对component容器的引用声明:
    As-Is:
    1
    2
    3
    4
    5
    6
    7
    <script>
    sap.ui.getCore().attachInit(function () {
    sap.ui.xmlview({
    viewName : "sap.ui.demo.wt.view.App"
    }).placeAt("content");
    });
    </script>

To-Be:

1
2
3
4
5
6
7
<script>
sap.ui.getCore().attachInit(function() {
new sap.ui.core.ComponentContainer({
name : "sap.ui.demo.wt"
}).placeAt("content");
});
</script>

在index.html根目录下新建文件Component.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
sap.ui.define(
["sap/ui/core/UIComponent"],
function(UIComponent) {
"use strict";
return UIComponent.extend("sap.ui.demo.wt.Component", {
//关联rootview
metadata : {
rootView: "sap.ui.demo.wt.view.App"
},
init: function() {
//call the init function of the parent
UIComponent.prototype.init.apply(this, arguments);
//定义OModel,并指定OModel路径
var oModel = new sap.ui.model.odata.ODataModel("/sap/opu/odata/sap/ZGJZ_PWD_RESET_SRV/");
//绑定oModel到view上
this.setModel(oModel);
}
});
});

可以看到这里首先用metadata/rootview来定义的应用打开的初始view,并且将Model的代码从Controller中挪了过来,真正实现了MVC结构。

  1. 调整Controller.js

再次执行程序,一样的效果说明我们的component加入成功

加入manifest和多语言i18n

在加入component之后,我们再来尝试加入manifest文件,同时将文本字段写到一个多语言的i18n.properties文件中集中进行维护。

  1. 在index.html根目录下新建文件manifest.json:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    {
    "_version": "1.1.0",
    "sap.app": {
    "_version": "1.1.0",
    "id": "sap.ui.demo.wt",
    "type": "application",
    "i18n": "i18n/i18n.properties",
    "title": "{{appTitle}}",
    "description": "{{appDescription}}",
    "applicationVersion": {
    "version": "1.0.0"
    }
    },
    "sap.ui": {
    "_version": "1.1.0",
    "technology": "UI5",
    "deviceTypes": {
    "desktop": true,
    "tablet": true,
    "phone": true
    },
    "supportedThemes": ["sap_belize"]
    },
    "sap.ui5": {
    "_version": "1.1.0",
    "rootView": "sap.ui.demo.wt.view.App",
    "dependencies": {
    "minUI5Version": "1.30",
    "libs": {
    "sap.m": {}
    }
    },
    "models": {
    "i18n": {
    "type": "sap.ui.model.resource.ResourceModel",
    "settings": {
    "bundleName": "sap.ui.demo.wt.i18n.i18n"
    }
    }
    },
    "contentDensities": {
    "compact": true,
    "cozy": true
    }
    }
    }

我们来分别理解一下这个APP配置文件中这些内容都是什么意思,其中像’version’这类直观就能看懂的就不再说了,捡几个重要的:

  • "id": 看内容应该也能猜到这里配置的是这个APP的resourceroot属性
  • "i18n": 配置了多语言文件的相对路径和文件名,一般都是"i18n/i18n.properties"
  • "rootView": 这里又将rootvie从component中挪到了这里来定义
  • "models": 至此我们发现model可以远处不在,可以在manifest中定义,可以在component中定义,可以在controller中定义,如果实在是懒甚至可以写在html中,但一个清晰的文件结构也是我们的学习内容之一,从此以后我们就尝试将model定义在manifest文件中,不论是JSONModel、XMLModel(最好以文件形式出现)还是ODataModel,都是在这里进行定义,WEBIDE提供的Descriptor Editor也方便我们直观的进行配置
  1. 调整Component.js
    1
    2
    3
    metadata : {
    manifest: "json"
    },

使用metadata/manifest来声明应用将使用的配置文件

  1. 创建i18n.properties
    接下来要建一个i18n文件夹和一个i18n.properties文件,这个文件完全可以理解成ABAP开发中的“文本元素”,就不多说了
  2. 替代文本元素
    接下来我们将view中的文本都替代到i18n文件中,下图可以看到一个修改后的和修改前的一个对比,这里我已经将“用户帐号”用{i18n>userID}进行了替代,其实利用WEBIDE的layout Editor维护起来非常的方便,比如下面的“手机号”文本,只需要点点击Text后面的链接按钮

    删除原来的文本,选择’i18n’,然后点击’+’

    在弹出的窗口中填入占位符和相应的文本

    把常量文本全部替换后App.view.xml和i18n.properties的样子,这样维护起来是不是轻松多了


    此时再执行程序,效果和原来一模一样:
  • 创建Model
    使用Descriptor Editor来创建oModel,以替换在component中定义oModel的语句:(同时可以看到在manifest文件中已经写入了ResourceModel的配置)






此时再执行程序,效果依然和原来一模一样:

至此,我们又成功加入的manifest.json和i18n.properties!

下面放上导出的完整代码,供参考:

http://pan.baidu.com/s/1pL2tb8B

参考

Create a neo-app.json Project Configuration File

JavaScript-NaoTu

发表于 2017-08-23 | 分类于 JavaScript | | 阅读次数

个人认为学习一门新知识的有效途径就是看前人整理的脑图,它可以做为学习的roadmap和也可以做为手边书进行查询备忘,Fiori开发过程中一定会用到JavaScript,下面是从网上down的一个系列的JavaScript脑图,FYI

  • 1、javascript数据类型
  • 2、javascript数组
  • 3、javascript运算符
  • 4、javascript正则表达式
  • 5、javascript字符串函数
  • 6、window对象
  • 7、DOM基本操作
  • 8、javascript变量
  • 9、javascript函数基础
  • 10、javascript流程控制

1、javascript数据类型

2、javascript数组

3、javascript运算符

4、javascript正则表达式

5、javascript字符串函数

6、window对象

7、DOM基本操作

8、javascript变量

9、javascript函数基础

10、javascript流程控制

没有找到图的原作者,如有侵权,请告知

1234…8
Jim Guo

Jim Guo

Hi~

36 日志
5 分类
22 标签
© 2018 Jim Guo
由 Hexo 强力驱动
主题 - NexT.Mist