Aurora实践
目录
目录 ...................................................................... 1 1典型界面 ................................................................ 3 1.1 一个简单的FORM-GRID程序概览 ...................................... 3
1.1.1 以“系统描述”为例 ................................................. 3 1.1.2 简析FORM ......................................................... 3 1.1.3重要属性BINDTARGET ................................................ 4 1.1.4简析GRID .......................................................... 5 1.1.5简述BM ............................................................ 7 1.1.6查询过程 .......................................................... 8 1.1.7新增和修改数据的保存 .............................................. 9 1.2单FORM录入 ........................................................... 9 1.3GRID多级联动 .......................................................... 9 1.3.1介绍GRID的多级联动 ............................................... 9 1.3.2GRID多级联动的查询 ............................................... 12 1.3.3头行保存的SVC写法 ............................................... 13 1.3.4头行保存的BM写法 ................................................ 15 1.4 FORM+GRID,头行一起保存 ............................................. 16 2客户端逻辑 ............................................................. 17 2.1页面元素的隐藏与显示 ................................................. 17 2.1.1纯JS方法隐藏一个组件 ............................................ 17 2.1.2隐藏和显示GRID中的某一列 ........................................ 17 2.1.3根据特定参数决定 ................................................. 17 2.2可变编辑器(GRID EDITORFUNCTION) ...................................... 18 2.3可输状态 ............................................................. 18 2.3.1硬编码方式的可输入状态 ........................................... 18 2.3.2通过JS控制可输入状态 ............................................ 19 2.4必输状态 ............................................................. 19 2.4.1硬编码方式的必输状态 ............................................. 19 2.4.2通过JS控制的必输状态 ............................................ 19 2.5 COMBO BOX二级联动 ................................................... 19 2.6动态设置LOV特性 ..................................................... 19 2.6.1设置LOV来源 ..................................................... 19 2.6.2设置LOV参数 ..................................................... 20 2.7对DATASET循环操作 ................................................... 20 2.7.1取RECORD数组的方法 .............................................. 20 2.7.2处理RECORD数组 .................................................. 20 3校验 ................................................................... 21 3.1常规客户端校验 ....................................................... 21
1
3.1.1必输字段校验 ..................................................... 21 3.1.2使用验证器校验 ................................................... 21 3.1.3根据头字段校验行字段 ............................................. 21 3.1.4根据行字段校验头字段 ............................................. 21 3.1.5通过AJAX执行SERVER端校验证 ..................................... 21 4 BM特性 ................................................................ 25 4.1查询 ................................................................. 25
4.1.1通过BASETABEL和FIELDS自动生成的查询 ............................ 25 4.1.2通过在BM中定义
2
1典型界面
在介绍实践内容之前,首先简单介绍一下Aurora框架的核心思想:
在web应用中,无论是用户向服务器提交的数据,还是服务器向用户返回的数据,都是具有一定含义的数据的集合。例如用户注册时可能要填写个人的基本信息、填写简历时需要填写工作经历、培训历程等,服务器向用户返回查询的航班信息等等,都是具有一定的含义的。这种数据的集合在Aurora框架中抽象为DataSet。在Aurora框架中,DataSet是web前端与服务器直接进行数据交换的介质,是Aurora框架前端AuroraUI中最核心的部分。
DataSet提供了对数据的操作和导航,对数据的操作会触发相应的事件(event),所有绑定(bind)到DataSet有UI组件会根据事件做出响应。
1.1 一个简单的form-grid程序概览
1.1.1 以“系统描述”为例
在HAP系统中,我们可以参考一下“系统描述”功能。(详情请参见下列清单)
一、 功能简述:用于程序页面的多语言,比如,当页面上有一条提示“查询条件”,
实际在编码时写入其对应的代码“HAP_QUERY_TITLE”,在实际运行时,会根据当前用户选择的local并配合程序中的code来唯一确定一条描述信息 二、 用到的页面文件(screen文件):sys_prompt.screen 三、 用到的业务模型文件(bm文件):sys_prompts.bm 四、 用到的数据库表:sys_prompts
五、 用到的数据库对象:sys_prompts_s(序列)
1.1.2 简析form
3
能力,使用form后,框架解析后生成的界面类似下图:
Form常见属性:
? column :表示了该表单每行有多少列,form中的组件当排满一行后会自动换行至下
一列。 ? width :表示了该表单的宽度,此属性可能会影响表单内控件的外观,当宽度较低时,
会产生意外的结果。
? title:如图中title所示。
? 未提到的属性信息,请参阅“Aurora Tag Documentation”文档
1.1.3重要属性bindTarget
在提到bindTarget属性时,首先先介绍一下Aurora框架页面端的基本编程概念。Aurora页面端采用数据和表示分离的思想,既页面端所有的数据均存放在Dataset(实际为一个js对象)中。Dataset中既存放有数据,又有该数据的附加信息,如对应字段是否必输,是否只读,还有内置的一些对数据的操作方法。
Dataset中可以有一条数据也可以有多条数据,这些数据的存在形式类似于数据表,可以认为dataset中有一张数据表,表中可以有一行或多行记录,这些记录被称作record。
页面中的许多数据元素要和一个dataSet进行绑定。比如,在一个form中输入查询条件,查询条件的输入控件又和一个dataset绑定,那么,这个查询条件就会以该输入组件的name属性为key,输入值为value绑定到此编辑器指定的dataSet上(准确的说是该dataset当前的record上)。sys_prompt.screen中对应查询的dataSet代码清单如下:
该dataset的声明较为简单,这里你只需要知道form中的查询控件是绑定到该dataset上即可。
再来看grid控件绑定的结果dataset
? autoQuery:值取boolean类型,默认为false。意为在页面加载完毕后是否自动进行
一次ajax方式的查询动作。
? selectable:表示查询结果是否可以被选中
4
? fetchAll:表示是否一次加载全部数据(不分页) ? pageSize:如果分页,每页的数据量 ? autoCount:显示结果计数
? queryDataSet:重要属性,指示查询时,用户可输入的查询条件来源。比如在此例中,
查询条件绑定的dataset称为A,结果grid绑定的dataset称为B,如果B的queryDataSet属性为A的ID,那么,当B调用其查询方法的时候,会将A中的数据取出作为附加的查询条件。
? queryUrl:指定了当前dataset查询数据时的url,其一般格式为:
${/request/@context_path}/autocrud/test.testbm/query?contractno=${/parameter/@contractno}
其一般可分成四部分:${/request/@context_path},取当前web应用的根路径,比如项目名配置为HAP,那么解析后便成为/HAP;autocrud,框架内置,调用框架处理增删改查的机制;test.testbm:前面的test指示bm的文件目录,从web-inf/classes/开始计算,本例中即为web-inf/classes/test/testbm.bm;query:指示该url对应的行为,目前总共有5个可用,query对应查询,insert对应新增,update对应更新,batch_update对循环应增删改,delete对应删除,execute可执行一个pl sql块。 ? model :此属性具有多重作用。首先,该属性值必须是一个bm文件路径(有关bm文
件的详细讲解内容,请参见本文档中介绍bm的部分,这里只是先做简单介绍),页面解析时,会对给定路径进行严格检查。当dataset中无queryUrl时,如果调用该dataset的query(),那么会尝试从指定bm文件自动生成查询语句;当dataset中无submitUrl时,如果调用该dataset的submit(),那么会尝试从指定的bm文件自动生成insert、update、delete语句。
? 其余未列出的属性见本文档DataSet详细介绍一节以及请参阅“Aurora Tag
Documentation”文档
此例中涉及到的grid中的子节点介绍如下:
? fields: field节点是对dataset中的字段的修饰。在上述代码中,字段prompt_code
被声明为“必填项”,当绑定在dataset上的控件有name=”prompt_code” 时,该控件既为必填项。同理,只读控制和其他控制均需在field中声明。
1.1.4简析grid
editorFunction=\/>
? bindTarget:说明其绑定的dataset。
? marginWidth、marginHeight:与页面布局有关的属性,详细请查阅HTML标准。 ? 未提到的属性信息,请参阅“Aurora Tag Documentation”文档
此例中涉及到的grid中的子节点介绍如下:
? toolbar:工具条,常用的有增加、保存、删除。此三按钮如果仅仅声明type属性,
则默认行为为调用绑定dataset的对应行为。 ? columns:数据列,说明要显示的结果列。
? name:显示的列名。比如当有结果名为user时,若name=”user”,则将值显示
在此列。
? sortable:表明可以按此列排序(当鼠标点击该列的标题时进行排序)。当此列
数据为子查询结果时不可用,否则会引发异常。
? editorFunction:指定一个处理函数,可以对数据的可编辑性进行控制。比如在
此例中,业务要求是当建立了一个prompt记录的时候,其code和语言类型均不可再被编辑。此属性对应的是一个js函数名,当业务逻辑允许该列修改数据时,可以在js中返回一个编辑器的ID,如果不允许修改,返回空即可。 function promptCodeEditFunction(record, name) { if (record.get('prompt_id')) { 6
return ''; } else { return 'sys_prompt_result_grid_upper_tf'; } } ? editors:编辑器。其子节点的类型指定编辑器的类型,id为该编辑器的id
1.1.5简述bm
Bm文件主要负责和数据库的交互,既可以是类似于hibernate一样对数据库结构进行映射,从映射中尝试自动生成增删改查语句,也可以自己写增删改查。一句话,bm文件主要是负责与数据库交互,增删改查和Ajax请求(需要和数据库交互)都要在bm中定义。具体信息,请参阅bm详解一节。
我们先把本例中的bm文件贴出来
本例中的bm文件,是对一张数据表的映射,从开头的baseTable=\alias=\可以看出来,对应的是sys_prompts表,同时取表别名为”f”。
prompt_code和query-field中的一个field对应,那么,就会按照后面queryOperator的规则拼接条件子句。要注意,如果query-field中声明的属性是 field,那么必须在上文中的 name=\/>节点。如果传递过来的参数是需要拼接一个自己定义的查询条件,需要将query-field声明为如下形式: Bm文件可以尝试生成对应请求的操作,比如如果过来一个query请求,bm可以根据定义的field来尝试生成query语句,在此例中,如果页面发来一个query请求,并且携带一个参数prompt_code,参数值为“HAP_QUERY”生成的query语句为 select f.prompt_id, f.prompt_code, f.language, decode(f.language, 'U', 'English', '简体中文') as language_display, f.description from sys_prompts f where f.prompt_code = 'HAP_QUERY' 1.1.6查询过程 此例中,查询的过程简要分析如下: 首先,如果用户在查询条件中输入值,比如在“描述字段”中输入”HAP_QUERY”, 8 然后点击“查询”。查询按钮绑定的函数为 function queryPrompt() { $('sys_prompt_result_ds').query(); } 即:取到负责显示结果的dataset,然后调用其内置的query方法。注意这里是调用负责显示结果的dataset,而不是查询条件所绑定的dataset。将从查询dataset中取出用户填写的值,即为prompt_code:’HAP_QUERY’,作为附加的查询条件。同时,如果dataset没有指定queryUrl(其实际地址是请求一个bm的query行为),那么会尝试从指定的model中生成一个查询语句;如果指定了,则按照指定url提交查询请求,queryUrl的优先级高于从model中生成。同时将取到的查询参数传递过去。Bm文件接到查询请求后,尝试从field定义中生成查询语句,查询完毕后,会以json格式将查询结果组装好,发至页面端,dataset接收数据后即通知绑定组件进行数据显示。至此整个查询过程完毕。 1.1.7新增和修改数据的保存 在本例中,单击页面上的“新增”按钮,即在grid中新增了一行记录,填写完毕后单击“保存”,即调用dataset的submit()方法,将页面上更改过的行(包括新增的)以json格式传递到bm中,bm文件可以根据每行的状态来生成相应的sql语句。这里类似于查询,当dataset中声明了submitUrl时,调用dataset的submit方法是以此url为提交地址;如果没有声明,则尝试从model属性指定的地址来生成url。 1.2单form录入 思路:form中组件绑定一个dataset,在该dataset中声明一个submitUrl,在写完相应数据后,点击保存按钮,调用dataset的submit()即可。具体可参考HAP系统中“系统设置”下“用户定义”中的“用户新增”。 1.3grid多级联动 在实际需求中,也有一种很重要的结构,即头行结构。就是汇总信息存在头表,明细信息存在行表。比如HAP系统中有“代码维护”应用。比如现在系统中有一代码“COMPANY_TYPE”(公司类型),其下有四种类型:业务实体、汇总公司、合并公司、调整公司。则类型代码是存在sys_codes表中,该代码下的具体值存放在sys_code_values表中。我们现在就以该应用为例,讲解一下如何编写头行结构的增删改查。 1.3.1介绍grid的多级联动 我们先来看一下程序运行的界面: 9 当我们选中头表记录中的“科目类型”的时候,行表自动刷新数据 10 我们先来看这是怎么做到的。 fetchAll=\ queryUrl=\FIELD=code_value\> 1.3.2Grid多级联动的查询 在头dataset上,我们声明了数据来源: 12 queryUrl=\,表明数据从sys_codes这个bm中获得,行dataset上,我们声明了 queryUrl=\ode_value\,表明了数据从sys_code_values这个bm中获得。当行dataset上声明了bandTarget=”sys_code_ref_ds”后,当头dataset中被选中的record的index发生改变时(在此应用中可以使简单的单击其他行),会自动将头的当前record中的所有数据当做行dataset的查询数据,进行一次行表的查询。这样,只要行表bm中有对应头记录的ID的条件子句时,就可以正确拼出查询sql。 1.3.3头行保存的svc写法 将头dataset的submitUrl声明为一个svc文件,在此例中,svc文件如下: 点击“保存”后的请求参数(已被格式化): _request_data : { \ : [ { \ : \, \ : \, \ : \, \ : \Emerson的测试code\, \ : [ { \ : \, \ : \优\, \ : \, \ : 1064, \ : \ }, { \ : \, \ : \良\, \ : \, \ : 1065, \ : \ }, { \ : \, \ : \中\, \ : \, \ : 1066, \ : \ }, { 14 \ : \, \ : \差\, \ : \, \ : 1067, \ : \ } ], \ : 1063, \ : \ } ] } 可以发现,我们提交过去的参数中又出现了个名为result_ds的json数组,其中正是我们在行表中填写的项。名字正是我们在行dataset中声明的bindName。 总体步骤是: 1、 在页面上写两个dataset,两个grid分别绑定上去; 2、 在行dataset上写属性bindTarget=“头dataset的ID”;bindName自行确定; 3、 将头dataset的submitUrl指向一个svc文件(切记提交时是提交头dataset); 4、 在svc文件中指明头数据的循环根路径; 5、 在svc文件中指明行数据的循环根路径; 6、 在行bm中,保存头表记录ID的字段,加入属性insertExpression insertExpression=\头表ID字段名} 详细代码请参见“HAP”系统中的“代码维护”功能。 1.3.4头行保存的bm写法 在BM中,通过 标签,可设置层级更新,例如: 15 这样,在对DEPT表进行批量更新时,每条DEPT主记录更新完毕后,会找当前主记录中名为 EMPLOYEE-LIST的下级记录集,并以testcase.HR.EMP为基础BM,对EMP表进行批量更新。输入参数的数据结构类似于: 如果要对多个detail表进行更新,那么在cascade-operations下面设置多条cascade-operation标记就可以了,没条对应一个detail表。 cascade-operation的属性: 属性 说明 inputPath detail记录在主记录中的访问路径 model detail记录对应的BM operations detail记录允许的操作,如insert,update,delete,execute等,用逗号分隔 1.4 Form+Grid,头行一起保存 方法其实和1.3中相同,只不过前一种的头dataset中有多条数据,此种情况中头dataset中只有一条数据而已。具体可参考1.3节。 16 2客户端逻辑 2.1页面元素的隐藏与显示 2.1.1纯js方法隐藏一个组件 可在需要隐藏的元素上声明id,再使用document.getElementById(id)取得组件,然后设置style属性display,none为隐藏,block为显示。代码示例如下 function hidetest() { var input = document.getElementById(\); input.style.display = \;// hide this element input.style.display = \;// } 2.1.2隐藏和显示grid中的某一列 取得grid(通过id),然后调用grid的hideColumn(column名)隐藏列,通过showColumn(column名)显示列: var grid = $(\); grid.hideColumn('testColumnName'); grid.showColumn('testColumnName'); 2.1.3根据特定参数决定 当需要根据某以参数决定显示与否的时候,采用如下结构。 17 2.2可变编辑器(grid editorFunction) 当有特殊需求时,比如在grid中,当前行为新增行时,行上的username列可以编辑,当保存后便不可编辑,实现步骤如下: 1、在grid的editors节点中加入一个编辑器,以textField为例 2、在目标column上声明属性editorFunction,指明一个函数: 2.3.1硬编码方式的可输入状态 比如在dataset ds中有绑定有控件username,在查看界面中是不可编辑的,操作步骤为: 1、在ds中的fields中声明子节点field,在field中声明属性 readOnly=”true” 2.3.2通过js控制可输入状态 在实际需求中,也经常有某字段根据一些条件来调整其可输入与否的特性。这种可以通过js代码来控制: var usernameField = record.getMeta().getField(\); usernameField.setReadOnly(true); 其中,record是当前正在操作的record(如果是form,可以认为是from中元素绑定的dataset的第一条record;如果是grid,则是高亮显示的行,默认选中第一行,然后随用户的操作改变)。 2.4必输状态 2.4.1硬编码方式的必输状态 同可输入状态一样,可在对应field上声明required=”true”。 2.4.2通过js控制的必输状态 同可输入状态一样,当取得字段对应的field对象后,调用setRequired(true)即可。 var usernameField = record.getMeta().getField(\); usernameField.setRequired(true); 2.5 combo box二级联动 2.6动态设置LOV特性 2.6.1设置lov来源 首先取得lov对应的field对象: var lovField = record.getMeta().getField(\); 然后有三种设置lov的方式 lovField.setLovModel(\model位置\); lovField.setLovService(\bm文件位置\); lovField.setLovUrl(\screen位置\); 19 2.6.2设置lov参数 首先先取得lov对应的field对象: var lovField = record.getMeta().getField(\); 然后通过 lovField.setLovPara('company_id', \); 这里就将lov中设置了一个默认的参数company_id,当点开lov时,此参数自动传入后台参数参与查询。此方法主要用于lov的联动,比如在汇率定义中,当用户选择了本币后,在选择外币时要将本币排除在结果列表外。 2.7对dataset循环操作 当遇到某些情况需要对dataset内的所有数据进行操作时,就要用到对dataset内容的循环操作。核心思想是将dataset中的所有record取出,循环处理每条record。 2.7.1取record数组的方法 常用的有两种方法,假如我们现在要取名为ds 的dataset中的record数组: var records=ds.getAll(); //取得该dataset下的所有record,返回一个js array对象。 var records=ds.getSelected();//取得所有用户选中的记录,返回一个js array对象。 2.7.2处理record数组 使用for循环遍历处理即可。比如要在每个选中的record中插入temp字段的值”Y”,处理过程如下: function test() { var ds = $(\);// 取得dataset对象 var records = ds.getSelected();// 取得record数组 for ( var i = 0; i < records.length; i++) { records[i].set(\, \); } } 20 3校验 3.1常规客户端校验 3.1.1必输字段校验 当在名为ds的dataset中有必输字段时,如果要对用户输入进行验证,既调用ds的validate()方法,即会对必输项进行校验。注意,该方法返回一个boolean值,如果有未填项,页面上会提示“校验不通过”来表示有未填项,并返回false,请根据返回值做进一步处理。 3.1.2使用验证器校验 3.1.3根据头字段校验行字段 3.1.4根据行字段校验头字段 3.1.5通过AJAX执行server端校验证 这是本框架中较为重要的一个技能,下面将详细介绍如何进行一次ajax校验 首先,介绍一个重要的框架内置js方法:Aurora.request。 Aurora.request({ url : url, params : para, opts : opts, success : function(response, options) { }, failure : function(response, options) { }, scope : scope }); 参数讲解: ? ? ? ? url:处理请求的url,通常是一个bm地址 params:携带的参数,需为json格式数据 opts:没用过 success:成功后的回调方法,接受两个参数,一个是返回的json对象,另一个是 21 ? failure:失败后的回调方法 ? scope:作用域 url参数有些讲究,我们先来分析一下url的结构,一个典型的url如下: ${/request/@context_path}/autocrud/sys.sys_testbm/execute 此url可以拆分成如下几部分: ? ${/request/@context_path}:取得应用的web根路径 ? autocrud: ? sys.sys_testbm:表示bm文件的位置,从web应用的web-inf/classes下开始查找,目录以“.”分 割,在此例中,该bm的位置是:web-inf/classes/sys/sys_testbm.bm。 ? execute:调用bm的行为。当要执行一段pl sql块时,这里就声明为execute。同时,bm中要有如 下结构: 除了execute,还有update。这里详细说一下这些参数应该在什么时候使用: 框架内置的一种机制,当dataset中新增一条record时(调用ds的add方法),会自动将record中的一个_status属性设置为insert;同理,当有一条数据更改时,会将其设置为update。比如当新增一条记录后,数据提交给bm时,如果url最后声明为insert,则 我们现在来以“注册新用户时用户名是否重复”这一假设来讲解如何用ajax方式进行校验。 假设素材: 页面:sys_user_new.screen Bm文件:sys_user_check.bm(在sys目录下) Pl sql包:sys_user_pkg 22 包内用到的过程:check_username( p_username varchar2 , p_resultcd out varcahr2); 首先,在screen文件中,通过Aurora.request方法进行ajax调用: Aurora.request({ url : \, params : { user_name : 'AA' }, opts : opts, success : function(response, options) { var result_cd = response.result.result_cd; if (result_cd == 0) { //业务逻辑上出错 } else { } }, failure : function(response, options) { }, scope : scope }); //业务逻辑的成功 这里的用户名我们假设为AA,实际应用中我们应当从用户的实际输入获取。当执行到此js代码时,浏览器即向服务器发送一个请求。地址为url中声明的地址,参数为params。 我们再来看bm端 首先bm中的 在这里我们根据返回的状态来做进一步处理,这就是整个的校验过程。 24 4 bm特性 Bm文件既可以是对数据表的映射,也可以定义数据库操作。它是框架自定义命名空间属性的xml文件,基于单张数据库表的,通过框架自定义的一些节点和tag,来定义一般表达业务逻辑的逻辑的文件。 4.1查询 一个bm文件是对一张数据表进行映射时(即特点是根节点中声明有baseTable属性,同时在bm文件内声明有fields节点),我们暂时假设此bm文件名为testbm.bm,所在位置是web-inf/classes/test/testbm.bm,同时,当页面发出一个查询请求时(不带任何查询参数) URL:${/request/@context_path}/autocrud/test.testbm/query} 从此url看出,请求的是该bm的query方法。 4.1.1通过baseTabel和fields自动生成的查询 如果该bm是对一张数据表(或多张表,以其中一张表为主表,通过bm中关联其他数据表的方法组织起来)的映射,那么框架会尝试从映射关系中生成查询语句 有时候自动生成的query语句无法满足需求(比如有union子句时),这时就需要自行写query语句。具体方法如下: ? operation name=\:这里必须将name的值写为query,当一个查询请求过来时,才能正确找到我们写的sql ? #WHERE_CLAUSE#:这里是为了和query-field配合使用,当有附加查询条件过来时,如果和 query-field中的能匹配上,则要在sql语句拼接条件子句。由于这时我们自己编写的查询,要给框架指明条件子句要拼接到什么地方。 ? 件子句,比如我们在expression 中写”1=1”,那么无论前面的sql如何,最终形成的sql语句中一定有 (and) 1=1 。 如果在没有任何附加查询条件的情况下,我们自己的sql本身就含有where子句(如表连接,默认查询条件等),需要特殊注意一下,我们不能写为如下形式: #WHERE_CLAUSE# ]]> 解决办法有两种: ? 将默认就有的where子句写在data-filter里; ? 将自己写的查询语句做嵌套,如上例,我们改造成如下形式: 如果在同一个bm中即符合可以自动生成查询sql的条件,又有自己书写的sql,那么,只会执行自行书写的bm。 4.2insert、update、delete 4.2.1通过框架自动生成 如果一个bm对应一张数据表,那么,可以自动生成对应的增删改语句。比如在HAP系统的“系统描述”功能中,当点击grid中的新增按钮时,会多出一行,当用户填写后点保存,会将数据传入bm,bm生成insert语句。 28 4.2.2通过在bm中定义 类似于查询,同样可以在bm文件中编写自己的insert语句。这里就不再赘述细节部分,和查询形式类似。 4.2.3使用insert、update、delete需要注意的内容 如果你希望不管什么时候都能够正确调用你自行书写的sql时,要时刻谨记以下内容: 之所以数据提交到后台,框架能够自动识别到底是新增还是修改还是删除,主要是有一个隐藏的参数来决定:_status。当在dataset上调用add()方法新增一行数据时(点“新增按钮”实际也是调用此方法),会在新生成的record中自动记录一个属性值 _status:insert。当一条记录有修改时,会自动修改此属性为update。当此记录传递到bm端时,bm靠此标记来确定到底应该调用什么行为。所以,如果你的dataset中没有新增的行,那么将数据传送到bm端时不会执行insert操作中的内容;同理可见update和delete。 4.2.4对batch_update的解释 当你的dataset中有多条数据有修改或新增时,最后点击“保存”按钮,会调用dataset的submit()方法。然后框架将dataset中所有修改过(包括新增)的record的数据组装成json格式传递到bm,submitUrl如下: /hclc/autocrud/sys.sys_service/batch_update 经过捕获,我们了解到传输参数的结构大致如下(已经经过格式化): { \ : [ { \ : 2202, \ : \, \ : \, \ : \, \ : \, \ : \, \ : \请勿555\, \ : 1022, \ : \ }, { \ : \, \ : \, \ : \, \ : \, \ : \, \ : \, \ : 1024, 29 \ : \ }, { \ : \二恶\, \ : \, \ : \, \ : \, \ : \, \ : \心iol\, \ : 1025, \ : \ } ] } 可以看出,传输过去的json格式的数据中有三组数据,一条update,两条insert。 Batch_update是框架中的一种实现机制,使后台能够循环处理每条传递过来的数据,并且根据_status来判断该如何处理每条数据。 4.3自定义BM的SQL出错信息 在bm里可以捕获直接捕获数据库抛出的异常信息,比如在bm中插入数据的主键重复异常。 做法如下: 1. 在bm的根节点声明命名空间。xmlns:e=\2. 在bm中增加如下子元素。 handleClass=\ Code:代表数据库抛出的异常代码。如主键重复代码ORA-00001,写成1. Message:针对该错误的提示信息 。如主键重复。写成“机型重复”。 4.4 多语言 4.5 Standard who 每个表都有四个字段:创建人,创建时间,更新人,更新时间。有该节点后,框架会自动维护这四个字段的信息。前题是所有的dml操作都是非自定义的。如果是自己定义的操作,如写的plsql过程。那么在plsql过程里就要自己维护了。 30 4.6Lookup code 表示该属性的值需要通过其他字段信息来描述. 如status有两个值,1和-1,我们需要表示成正常和不正常。Status的lookupCode值是status_code.那么该属性值写上lookupCode=”status_code”就行了。Status_code的值是表示正常和不正常的代码。真正的正常和不正常的值的表示还需要配个lookupField属性, lookupField=” Status_code_description 4.7执行动态SQL 动态sql,就是根据传入的条件的不同,执行不同的sql语句得到不同的sql结果。 语法:excute immediate <动态sql> into <输出参数>。 如下例子: begin --执行行头校验,出错退出程序 for i in 1 .. 21 loop v_sql := ' select a.attribute_' || i || ' from fnd_interface_lines a where a.line_id = ' || xxx || ' order by a.header_id desc, a.line_id asc'; execute immediate v_sql into sss(i); end loop; exception when others then null; end ; 本例是查询多个值放到数组sss(i)中。Sss的定义这里省略。Xxx代表变量参数。 在bm的自定义的操作中,即就是在operation节点中需要执行动态sql来完成你的逻辑。可仿照此例。 31 5各种组件 注:展示组件需要放到view标签中。 5.1 vbox,hbox 5.1.1vbox box组件类似于html中的div标签,在页面上不做显示,用于控制其他组件的位置,相当于一个布局容器。 vBox组件在box组件的基础上添加了竖向排列的限制,在vBox中的组件全部纵向排列,相当于column恒等于1,因此不需要设置column属性限制列数。 例如:在screen文件中有如下代码: hBox在box组件的基础上添加了横向排列的限制,在hBox中的组件全部横向排列,相当于row属性恒等于1,因此不需要设置row属性,例如有如下代码: 32 5.2 form布局 5.2.1 form的显示效果 form在box的基础上多提供了一个title,代码如下: 5.2.2 form的常用属性 form的常用属性除了title外,还有width(宽),height(高),column(列数),row(行数)属性,下面的代码将创建一个宽300,高120,2行,2列的form。如图下: 5.3 Auto Complete 5.4 通过任意html模板布局 5.5 tree 5.5.1 tree的构建方法 tree用于构建一个树对象,通常用于构建菜单,或者复杂的机构层次,显示效果如下: 33 树中的每个节点都是所绑定的数据集(dataset)中每一条记录(record) 节点与节点之间的层次关系是通过tree标签的属性idField和parenFeild来联系的,idField属性指定的是record中用来表示该节点的唯一标识(ID)的字段(field)名,parentField属性指定的record中用来表示该节点的父节点的ID和field名。 Tree标签的属性displayField指定的record中用来表示节点文本信息的field名。 下面的代码将构建一个简单的树。 5.5.2 tree的树节点渲染 通过节点渲染,我们可以为树节点添加超链接。在tree标签中指定renderer渲染函数实现。 代码如下: 34 节点的颜色变为超链接的颜色,点击后可以连接到相应的url页面。 5.6treeGrid 5.6.1 treeGrid的构建方法 和tree类似,treeGrid需要指定父节点,显示的字段,和当前节点ID。但同时也集成了grid的一些特性,可以通过columns标签指定多个显示域,实例代码如下: 5.6.2 treeGrid节点渲染方法 treeGrid通过使用editors标签渲染节点,修改代码如下: 5.6 grid列锁定(lock),复合表头 在实际需求中,有时候需要在grid的显示上做一些特殊的处理,目前我们已知的有两种特殊的需求:锁定grid中的某一列,以便在拖动grid上的横向滚动条(如果存在)时,被锁定的列始终保持固定在列表的最左侧;另一种是将一行表头分为多行,以起到合并同类项的效果 5.6.1锁定列 我们首先来看一下锁定列的效果,如下图,我们在查询结果中锁定“概算书编号”这一列,其余列不做特殊处理,效果如图: 36 1锁定列效果1 2锁定列效果2 实现方法: 在需要锁定的column上加入lock=”true”属性。 5.6.2复合表头 若要实现如下形式的表头 可以将需要组合的列用column组合 5.7 各种提示(showmessage,showconfirm) 5.7.1 showmessage和showconfirm 代码如下,showmessage只有一个确认按钮,而showconfirm可以选择确定或者取消,点击按钮后可以执行参数相应的回调函数。 function drop(){ if(true){ Aurora.showMessage('title','messages'); }else{ Var fc=Aurora.showConfirm('标题','消息内容',function(){ 38 Aelrt(‘1’); Fc.close();}); } } 显示效果如下: Showmessage的显示效果 showConfirm的显示效果 点击确定后显示: 需要注意的是,框架中的showconfirm和基本js的confirm不同,框架中的确认框起不到阻塞作用,而基本js可以。示例如下: function testConfirm() { var result = false; var comfirm = Aurora.showConfirm('title', '确定提交?', function() { //点“是”后的回调 result = true; }, function() { //点“否”后的回调 39 result = false; }, null, 100); return result; } 现给出情景如下:出现确认框后,当用户点击“是”的时候,请判断该函数返回的结果是true还是false? 如果用户无法用比程序顺序执行的速度还要快的速度去点击“是”的话,那么不论用户点什么按钮,始终返回的是false。 因为框架中的确认框是非阻塞性的,在给出确认框的同时,程序顺序执行到下一步,即return结果。 5.8 tab的用法 5.8.1 tab的使用 在screen文件中我们通过 如未指定selected属性,则默认为第一个tab页为选中状态。 41