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