OAF开发中一些LOV相关技巧 (转)

原文地址:OAF开发中一些LOV相关技巧

OAF开发中,LOV的使用频率是很高的,它由两部分构成一是页面上的LOV输入框(如OAMESSageLovInputBean),二是弹出的LOV模式窗口(OAListOfValueBean)。用户选择LOV的按钮就会弹出LOV窗口,用户在LOV窗口查询并选择了值,可以返回到页面上的LOV输入框。在这里就不赘述如何创建LOV,只说一些平时会碰到的应用:

1.控制LOV的查询结果 
2.LOV相关事件 
3.动态LOV 
4.LOV Choice
一,控制LOV的查询结果

1,使用Criteria

很多种情况下都会用到用某一个Item或者某几个Item来控制LOV的结果,例如页面上有一个Item的LOV和一个Organization,因为Item是有库存组织的,所以就有这样的需求,我选择了某一个库存组织的时候,Item的LOV只显示该库存组织下面的Item。

要实现这个功能,首先需要将Organization放入LOV查询语句作为结果集(LOV的VO中加入Oraganization_Id这一列),然后在Item的LOV中新建一个Mapping,Mapping中LOV Region Item选择OrganizationId(LOV中的),而Criteria选择页面上的OrganizationId,注意,这两个不是同一个Organization。一个是LOV中的,一个是页面上的。

Criteria设置了相应的Item时,在弹出LOV窗口时,会作为验证字段带入LOV窗口,LOV视图对象会自动绑定该值作为查询条件。因为这个自动绑定是对查询的结果集再进行一次条件查询,所以需要将Organization_Id作为查询结果集。

2,Passive Criteria

LOV的Criteria Item也可以手动绑定,也就是在主页面上的作为Criteria Item的字段在传入LOV Region后并不和LOV的查询自动绑定,而是由开发员动态去绑定。这种方法我认为是为了一些高级的查询所设的,例如需要根据传入的一个Flag字段,在查询条件中加入exists…这样的查询条件。

使用Passive Criteria,和LOV的普通Criteria Mapping一样,选择LOV Region Item以及Criteria Item,然后将Programmatic Query选择为True,这样,LOV就不会动态绑定查询条件了。之后,我们在LOV的Region上创建一个CO,在processRequest中得到验证字段:

public void processRequest(OAPageContext pageContext, OAWebBean webBean)
{
super.processRequest(pageContext, webBean);
OAApplicationModule am = pageContext.getApplicationModule(webBean);
Dictionary passiveCriteria = pageContext.getLovCriteriaItems();
//此处的LookupType指的是Mapping中的Lov Region Item的ID
String lovCriteria = (String)passiveCriteria.get("LookupType");

OAViewObject lovVO = (OAViewObject)am.findViewObject("FndLookupTypeLovVO1");
//根据得到的验证字段限定查询结果
lovVO.setWhereClause("");
lovVO.executeQuery();
} 

二、LOV事件

对于MessageTextInput,CheckBox等,可以使用Client Action来触发事件,假如一个CheckBox,可以为它做一个fireAction来控制比如打勾了以后改变某一个字段的值或者一些类似的控制。这些事件可以在页面CO中的processFormRequest中使用pageContext.getParameter(EVENT_PARAM)获得。但是MessageLovInput是没有fireAction事件的,实际上Lov操作的时候已经存在了一些事件,不需要我们去定义的,可以直接通过pageContext.getParameter(EVENT_PARAM)得到LOV事件。

LOV事件有三种,lovPrepare、lovUpdate、lovValidate(由pageContext.getParameter(EVENT_PARAM)返回),它们都是在页面CO的processFormRequest中触发的。当点了Lov上的手电筒时,会触发事件lovPrepare。当选中了某一个Lov返回到本页面是,会在formRequest中触发事件lovUpdate。当在Lov输入框中输入一个唯一的值时,此时会触发Lov验证,这里需要注意的是如果在输入框中输入一个不唯一的值,那么验证会自动的打开Lov窗口让你进行选择,此时在formRequest中是不会触发lovValidate事件的。当在选择了LOV选择的值进行相应的页面处理(例如控制其他字段是否显示等),就可以在processFormRequest中通过对Lov事件的判断并做相应处理。

/**Item版本控制,当选择了有版本控制的Item,该行版本字段可修改,如果没有版本控制,该Item版本字段为默认**/
super.processFormRequest(pageContext, webBean);
OAApplicationModule am = pageContext.getApplicationModule(webBean);
if("ItemCode".equals(pageContext.getLovInputSourceId()))
{ 

/**lovUpdate是在Lov Region选择了Item,lovValidate是在Lov MessageInput控件中输入后触发,在此事件中判断Item是否具有版本控制**/
if( "lovUpdate".equals(pageContext.getParameter(EVENT_PARAM))
|| "lovValidate".equals(pageContext.getParameter(EVENT_PARAM)))
{
/**对Revision字段进行控制**/
am.invokeMethod("controlRevSwitcher", new Serializable[]
{pageContext.getParameter(SOURCE_PARAM),
pageContext.getParameter("OrganizationIdFV")});

/**controlRevSwitcher方法是对版本控件的ReadOnly进行控制,但是页面上不能马上反应,需要使用局部刷新**/
OAAdvancedTableBean tableBean =
(OAAdvancedTableBean)webBean.findChildRecursive("VenTrxLinesAdvTbl");
tableBean.queryData(pageContext);
}
} 

在上例的例子中,由于LOV字段是基于VO的,所以得到所选的LOV的值可以在VO中得到。但是对于不基于VO的LOV,如果需要在页面事件发生的时候就得到选择得到的LOV值,需要用以下方法来获取:

// Form. was submitted because the user selected
// a value from the LOV modal window,
// or because the user tabbed out of the LOV input.
// Find out which LOV input triggered the event.
String lovInputSourceId = pageContext.getParameter(SOURCE_PARAM);
// Find out the result values of the LOV.
Hashtable lovResults =
pageContext.getLovResultsFromSession(lovInputSourceId);
if (lovResults != null)
{
System.out.println("lovResults"+lovResults);
// Update the page depending on the value chosen by the user.
} 

三、动态LOV

动态LOV的应用一般很少。在之前沈辉写的一个文档中,是通过先创建一个LOV后,然后在页面事件发生时动态的去改变LOV的SQL实现的。而我的方法是用直接动态创建VO去和LOV Region中的Item进行关联来实现的。

LOV是通过页面调用我们创建好的Region来实现的,所以这个LOV Region是LOV最为关键的部分,所以实际上,在LOV VO还不存在的时候,只要有Region,我们的LOV就可以创建起来。所以我们可以先创建一个空壳Region,然后在主页面打开的时候再动态的创建LOV VO,最后将VO与Region中的Table关联。


首先,需要创建一个LOV Region,这个Region并不和任何VO关联,在我的例子中,我创建了5个MessageStyledText,5个FormValue。这些字段字段此时只是设置了Prompt属性,其他属性都是默认,包括Data Type。

接下来,在主页面的ProcessRequest创建LOV Bean(当然也可以在其他页面动作的时候创建LOV)。并且创建LOV VO。import java.io.Serializable;

import java.util.ArrayList;
import java.util.Hashtable;

import oracle.apps.fnd.common.VersionInfo;
import oracle.apps.fnd.framework.OAApplicationModule;
import oracle.apps.fnd.framework.webui.OAControllerImpl;
import oracle.apps.fnd.framework.webui.OAPageContext;
import oracle.apps.fnd.framework.webui.beans.OAWebBean;
import oracle.apps.fnd.framework.webui.beans.layout.OAHeaderBean;
import oracle.apps.fnd.framework.webui.beans.message.OAMessageLovInputBean;

public void processRequest(OAPageContext pageContext, OAWebBean webBean)
{
super.processRequest(pageContext, webBean);
OAApplicationModule am = pageContext.getApplicationModule(webBean);

/*--------------------------------------------------创建LOV Bean----------------------------------------------------*/

OAHeaderBean headerBean = (OAHeaderBean)webBean.findChildRecursive("TestHdRN");
OAMessageLovInputBean lovInput = (OAMessageLovInputBean)createWebBean(pageContext, LOV_TEXT, null, "InputTest");

headerBean.addIndexedChild(lovInput);

// Specify the path to the base page.
lovInput.setAttributeValue(REGION_CODE, "/alther/oracle/apps/cux/checkboxtest/webui/CheckBoxTestPG");
// Specify the application id of the base page.
lovInput.setAttributeValue(REGION_APPLICATION_ID, new Integer(30001)); 

//此处的Region就是刚才创建的Region
lovInput.setLovRegion("/alther/oracle/apps/cux/lov/webui/CommonLovRN", 0);

lovInput.setUnvalidated(false);
lovInput.setPrompt("Dynamic Lov");

//增加Mapping关系,由于LOV的Mapping在主页面初始化时就会使用到,所以必须创建一些空的Item来做Mapping,否则会报错
lovInput.addLovRelations(pageContext, "InputTest", // base page item
"DisplayItem1", // lov item
LOV_RESULT, // direction
LOV_REQUIRED_NO);
lovInput.addLovRelations(pageContext, "InputTest", // base page item
"DisplayItem1", // lov item
LOV_CRITERIA, // direction
LOV_REQUIRED_NO); 

lovInput.addLovRelations(pageContext, "TestItem", // base page item
"DisplayItem2", // lov item
LOV_PASSIVE_CRITERIA, // direction
LOV_REQUIRED_NO); 

/*--------------------------------------------------创建LOV VO------------------------------------------------------*/
ArrayList paramList = new ArrayList();
String voName = "FndUserLovVO2";
String sql = "SELECT fu.user_id," +
" fu.user_name," +
" fu.start_date" +
" FROM fnd_user fu";

//paramList是用来创建LOV并在关联时都会用到的每个Item的Attribute
paramList.add(new String[]{"UserId", "USER_ID", "oracle.jbo.domain.Number", null, "Hide", null});
paramList.add(new String[]{"UserName", "USER_NAME", "java.lang.String", "100", "Display", "SearchAllow"});
paramList.add(new String[]{"StartDate", "START_DATE", "oracle.jbo.domain.Date", null, "Display", null});
//调用AM方法创建VO
am.invokeMethod("createVO", new Serializable[]{voName, sql, paramList},
new Class[]{String.class, String.class, paramList.geTCLass()});

am.getOADBTransaction().putTransientValue("LovVOInstance", voName);
am.getOADBTransaction().putTransientValue("LovAttribute", paramList);

} 

这是AM中创建VO的方法:

import java.sql.Types;

import java.util.ArrayList;

import oracle.apps.fnd.framework.server.OAApplicationModuleImpl;
import oracle.apps.fnd.framework.server.OADBTransaction;
import oracle.apps.fnd.framework.server.OAViewDef;

import oracle.jbo.AttributeDef;

public void createVO(String voName, String sql, ArrayList list){
OADBTransaction dbtx = getOADBTransaction();
String[] attribute = new String[6];
int types = -9999;
OAViewDef viewDef = dbtx.createViewDef();

viewDef.setSql(sql);
viewDef.setExpertMode(true);
viewDef.setViewObjectClass("oracle.apps.fnd.framework.server.OAViewObjectImpl");
viewDef.setViewRowClass("oracle.apps.fnd.framework.server.OAViewRowImpl");

for(int i = 0; i < list.size(); i++){
attribute = (String[])list.get(i);
if("java.lang.String".equals(attribute[2])){
types = Types.VARCHAR;
}
else if("oracle.jbo.domain.Number".equals(attribute[2])){
types = Types.NUMERIC;
}
else if("oracle.jbo.domain.Date".equals(attribute[2])){
types = Types.DATE;
}

if("java.lang.String".equals(attribute[2])){
viewDef.addSqlDerivedAttrDef( attribute[0],
attribute[1],
attribute[2],
types,
false,
true,
AttributeDef.UPDATEABLE,
Integer.parseInt(attribute[3]));
}
else{
viewDef.addSqlDerivedAttrDef( attribute[0],
attribute[1],
attribute[2],
types,
false,
true,
AttributeDef.UPDATEABLE); }
}

if(findViewObject(voName) != null){
findViewObject(voName).remove();
}

createViewObject(voName, viewDef);
} 

最后,在LOV Region的CO中,加入关联的代码。这里需要注意一点,由于我们的LOV VO是创建在主页面的AM下的,所以LOV Region的AM必须和主页面的AM一致。否则,在主页面的变量就无法传到LOV Region中。

public void processRequest(OAPageContext pageContext, OAWebBean webBean)
{
super.processRequest(pageContext, webBean);
OAApplicationModule am = pageContext.getApplicationModule(webBean);

String voInstance = (String)am.getOADBTransaction().getTransientValue("LovVOInstance");
ArrayList paramList = (ArrayList)am.getOADBTransaction().getTransientValue("LovAttribute");
String[] attribute = new String[6];
int dispalyIndex = 1;
int hideIndex = 1;

//关联VO
((OAListOfValuesBean)webBean).setViewUsageName(voInstance); 

//将Region中的MessageStyledText都设置为不显示
for(int i=1; i<=5; i++){
OAMessageStyledTextBean displayItem =
(OAMessageStyledTextBean)webBean.findChildRecursive("DisplayItem"+i);
displayItem.setRendered(false);
}

//将Region中的FormValue都设置为不显示
for(int i=1; i<=5; i++){
OAFormValueBean hideItem =
(OAFormValueBean)webBean.findChildRecursive("FormVal"+i);
hideItem.setRendered(false);
}

for(int i=0; i<paramList.size(); i++){
attribute = (String[])paramList.get(i);
if(attribute[4] != null && "Display".equals(attribute[4])){
OAMessageStyledTextBean displayItem =
(OAMessageStyledTextBean)webBean.findChildRecursive("DisplayItem"+dispalyIndex);

//关联View Attribute
displayItem.setViewAttributeName(attribute[0]);

//设置Data Type
if("java.lang.String".equals(attribute[2])){
displayItem.setDataType("VARCHAR2");
}
else if("oracle.jbo.domain.Number".equals(attribute[2])){
displayItem.setDataType("NUMBER");
}
else if("oracle.jbo.domain.Date".equals(attribute[2])){
displayItem.setDataType("DATE");
}
//设置显示
displayItem.setRendered(true);

//是否可查询
if(attribute[5] != null && "SearchAllow".equals(attribute[5])){
displayItem.setQueryable(true);
}

dispalyIndex++;
}
else if(attribute[4] != null && "Hide".equals(attribute[4])){
OAFormValueBean hideItem =
(OAFormValueBean)webBean.findChildRecursive("FormVal"+hideIndex);

//hideItem.setViewUsageName("FndUserLovVO2");
hideItem.setViewAttributeName(attribute[0]);

if("java.lang.String".equals(attribute[2])){
hideItem.setDataType("VARCHAR2");
}
else if("oracle.jbo.domain.Number".equals(attribute[2])){
hideItem.setDataType("NUMBER");
}
else if("oracle.jbo.domain.Date".equals(attribute[2])){
hideItem.setDataType("DATE");
}

hideItem.setRendered(true);

hideIndex++;
}
}
} 

由于是测试页面,所以Region Table的Prompt和Table中Item的Prompt并没有设上去。

四、LOV Choice

LOV Choice并不常用,实现起来也比较简单,它结合了下拉列表和LOV的特性,实际上就是将LOV常用的一些行放到列表中来:

当点击More的时候,会弹出来LOV Region,在Region选中的行,在之后会保存在列表中(可能是放在IE缓存中),以方便之后选择。

由于有下拉列表的特性,所以LOV Choice在下拉列表的时候只能有两列,而多余的列只能在LOV中显示。

1.创建LOV Region,需要注意的是LOV中用来作为列表返回值的列,长度不超过30 
2.在页面中创建一个Item,类型选择messageLovChioce,设置External LOV属性 
3.设置messageLovChioce的Picklist Display Attribute属性和Picklist Value Attributes属性,这个和下拉列表差不多,一个作为messageLovChioce真正的值,一个作为返回值。 
4.Lov Mapping和平常一样,返回值必须和messageLovChioce相对应,并且,Criteria Item属性必须为空(否则会报错)。

时间: 2024-12-22 05:18:12

OAF开发中一些LOV相关技巧 (转)的相关文章

EBS OAF开发中实体对象和视图对象的属性设置器

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 源文: Home > Oracle Application Framework Documentation Set, Release 12.2 > Oracle Application Framework Developer's Guide > Chapter 5: Implementing Server-Side Features > Entity Object and Vi

EBS OAF开发中的错误/异常处理(ErrorHandling) (转)

原文地址 EBS OAF开发中的错误/异常处理(ErrorHandling) EBS OAF开发中的错误/异常处理(ErrorHandling) (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 总览 这篇文档描述了如何在你的Model和控制器代码中抛出OAF 框架异常. 内容 l  异常类型 l  异常类 l  批量异常 l  异常示例 l  对话框页和消息对话框 异常类型 OAF框架处理三种基本类型的异常:常规(general),验证(

EBS OAF 开发中的OAQueryBean的三种构造模式

EBS OAF 开发中的OAQueryBean的构造模式 (版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 当你为pageLayout区域添加一个query 区域时,OAF框架生成一个oracle.apps.fnd.framework.webui.beans.layout.OAQueryBean对象,它依赖于它的配置,并通过一个子控件table, advanced table或者HGrid来实现simple search, advanced

EBS OAF开发中如何实现功能页签(Global Tab)

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 功能页签的实现不需要任何编码,和subTab不一样,可以和subTab共存.其主要实现是靠配置,步骤如下: 1.      建立两个OAF页面的Function. 2.      为每个function分别建立一个HTML Tab 类型的菜单,并把相应的Function加入到菜单中,但不要声明Prompt,如下: 3.      建立一个Home Page类型的菜单,并把上面建立的两个HTM

EBS OAF开发中如何通过ReferenceAO进行验证

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) Reference AO 除了用于VO中的数据展示,还可以用于对EO进行辅助验证,比如在示例中建立的Employee和Manager的AO,假设如果有Employee的工资不能比其Manager的工资的高的验证就可以通过AO在EO轻松实现. 1.      AO的创建参考之前的文章和OAF Tutorial 示例代码,在AO设置可以在Employee EO访问Manager EO,这里的Ac

EBS OAF开发中实现参数式弹出窗口

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 概览 参数式弹出窗口和嵌入式弹出窗口不一样,它拥有独立的区域,并不嵌入到使用页面中,它里面的内容根据需要来获取和生成,它拥有自己的AM和页面状态,对popup页面事件的处理也不一样.两种弹出式窗口都只在下面四种组件所支持,既不能改变大小也不可移动. 1.        Text(messageStyledText) 2.        Image 3.        Link 4.     

EBS OAF开发中实现參数式弹出窗体

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) 概览 參数式弹出窗体和嵌入式弹出窗体不一样,它拥有独立的区域,并不嵌入到使用页面中,它里面的内容依据须要来获取和生成,它拥有自己的AM和页面状态,对popup页面事件的处理也不一样.两种弹出式窗体都仅仅在以下四种组件所支持,既不能改变大小也不可移动. 1.        Text(messageStyledText) 2.        Image 3.        Link 4.    

EBS OAF开发中的Java 实体对象(Entity Object)验证功能补充

(版权声明,本人原创或者翻译的文章如需转载,如转载用于个人学习,请注明出处:否则请与本人联系,违者必究) EO理论上是只有产品组维护,里面包含其所有的业务逻辑,并提供相应的Expert给自己或者其它产品组使用.而VO是各个组根据需要或基于EO或者只读的SQL而建立的,里面可以根据需要添加自己的业务实现和逻辑. 对于EO内部的验证功能,在开发文档中主要介绍了三种: 1. 在setter里面实现单个属性的验证.这主要是对于没有依赖关系的属性,也就是说它的验证不需要其它会被修改的属性的支持.比如,验证

一探前端开发中的JS调试技巧

前言:调试技巧,在任何一项技术研发中都可谓是必不可少的技能.掌握各种调试技巧,必定能在工作中起到事半功倍的效果.譬如,快速定位问题.降低故障概率.帮助分析逻辑错误等等.而在互联网前端开发越来越重要的今天,如何在前端开发中降低开发成本,提升工作效率,掌握前端开发调试技巧尤为重要. 本文将一一讲解各种前端JS调试技巧,也许你已经熟练掌握,那让我们一起来温习,也许有你没见过的方法,不妨一起来学习,也许你尚不知如何调试,赶紧趁此机会填补空白. 骨灰级调试大师Alert 那还是互联网刚刚起步的时代,网页前