ITPub博客

首页 > 数据库 > Oracle > OAF开发中一些LOV相关技巧

OAF开发中一些LOV相关技巧

Oracle 作者:kawontony 时间:2019-08-16 20:33:58 0 删除 编辑

转自:https://liang-wenfu.iteye.com/blog/1066755

在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中得到验证字段: 


  1. public   void  processRequest(OAPageContext pageContext, OAWebBean webBean)  
  2. {  
  3.    super .processRequest(pageContext, webBean);  
  4.   OAApplicationModule am = pageContext.getApplicationModule(webBean);  
  5.   Dictionary passiveCriteria = pageContext.getLovCriteriaItems();  
  6.    //此处的LookupType指的是Mapping中的Lov Region Item的ID   
  7.   String lovCriteria = (String)passiveCriteria.get( "LookupType" );  
  8.    
  9.   OAViewObject lovVO = (OAViewObject)am.findViewObject( "FndLookupTypeLovVO1" );  
  10.    //根据得到的验证字段限定查询结果   
  11.   lovVO.setWhereClause( "" );  
  12.   lovVO.executeQuery();  
  13. }   



二、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事件的判断并做相应处理。


  1. /**Item版本控制,当选择了有版本控制的Item,该行版本字段可修改,如果没有版本控制,该Item版本字段为默认**/   
  2. super .processFormRequest(pageContext, webBean);  
  3. OAApplicationModule am = pageContext.getApplicationModule(webBean);  
  4. if ( "ItemCode" .equals(pageContext.getLovInputSourceId()))  
  5. {   
  6.    
  7.    /**lovUpdate是在Lov Region选择了Item,lovValidate是在Lov MessageInput控件中输入后触发,在此事件中判断Item是否具有版本控制**/   
  8.    if (    "lovUpdate" .equals(pageContext.getParameter(EVENT_PARAM))  
  9.      ||  "lovValidate" .equals(pageContext.getParameter(EVENT_PARAM)))  
  10.   {  
  11.      /**对Revision字段进行控制**/   
  12.     am.invokeMethod( "controlRevSwitcher" new  Serializable[]   
  13.                                   {pageContext.getParameter(SOURCE_PARAM),  
  14.                                    pageContext.getParameter( "OrganizationIdFV" )});  
  15.    
  16.    
  17.      /**controlRevSwitcher方法是对版本控件的ReadOnly进行控制,但是页面上不能马上反应,需要使用局部刷新**/   
  18.     OAAdvancedTableBean tableBean =   
  19.         (OAAdvancedTableBean)webBean.findChildRecursive( "VenTrxLinesAdvTbl" );  
  20.     tableBean.queryData(pageContext);  
  21.   }        
  22. }




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

  1. // Form was submitted because the user selected   
  2. // a value from the LOV modal window,   
  3. // or because the user tabbed out of the LOV input.   
  4. // Find out which LOV input triggered the event.   
  5. String lovInputSourceId = pageContext.getParameter(SOURCE_PARAM);  
  6. // Find out the result values of the LOV.   
  7. Hashtable lovResults =  
  8.     pageContext.getLovResultsFromSession(lovInputSourceId);  
  9. if  (lovResults !=  null )  
  10. {  
  11.     System.out.println( "lovResults" +lovResults);  
  12.      // 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。



  1. import  java.io.Serializable;  
  2.    
  3. import  java.util.ArrayList;  
  4. import  java.util.Hashtable;  
  5.    
  6. import  oracle.apps.fnd.common.VersionInfo;  
  7. import  oracle.apps.fnd.framework.OAApplicationModule;  
  8. import  oracle.apps.fnd.framework.webui.OAControllerImpl;  
  9. import  oracle.apps.fnd.framework.webui.OAPageContext;  
  10. import  oracle.apps.fnd.framework.webui.beans.OAWebBean;  
  11. import  oracle.apps.fnd.framework.webui.beans.layout.OAHeaderBean;  
  12. import  oracle.apps.fnd.framework.webui.beans.message.OAMessageLovInputBean;  
  13.    
  14. public   void  processRequest(OAPageContext pageContext, OAWebBean webBean)  
  15. {  
  16.    super .processRequest(pageContext, webBean);  
  17.   OAApplicationModule am = pageContext.getApplicationModule(webBean);  
  18.    
  19.    /*--------------------------------------------------创建LOV Bean----------------------------------------------------*/   
  20.    
  21.   OAHeaderBean headerBean = (OAHeaderBean)webBean.findChildRecursive( "TestHdRN" );  
  22.   OAMessageLovInputBean lovInput = (OAMessageLovInputBean)createWebBean(pageContext, LOV_TEXT,  null "InputTest" );  
  23.    
  24.   headerBean.addIndexedChild(lovInput);  
  25.    
  26.    // Specify the path to the base page.   
  27.   lovInput.setAttributeValue(REGION_CODE,  "/alther/oracle/apps/cux/checkboxtest/webui/CheckBoxTestPG" );  
  28.    // Specify the application id of the base page.   
  29.   lovInput.setAttributeValue(REGION_APPLICATION_ID,  new  Integer( 30001 ));      
  30.    
  31.    //此处的Region就是刚才创建的Region   
  32.   lovInput.setLovRegion( "/alther/oracle/apps/cux/lov/webui/CommonLovRN" );  
  33.    
  34.   lovInput.setUnvalidated( false );  
  35.   lovInput.setPrompt( "Dynamic Lov" );  
  36.    
  37.    //增加Mapping关系,由于LOV的Mapping在主页面初始化时就会使用到,所以必须创建一些空的Item来做Mapping,否则会报错   
  38.   lovInput.addLovRelations(pageContext,    "InputTest" // base page item   
  39.                                            "DisplayItem1" // lov item   
  40.                                           LOV_RESULT,  // direction   
  41.                                           LOV_REQUIRED_NO);  
  42.   lovInput.addLovRelations(pageContext,    "InputTest" // base page item   
  43.                                            "DisplayItem1" // lov item   
  44.                                           LOV_CRITERIA,  // direction   
  45.                                           LOV_REQUIRED_NO);      
  46.    
  47.   lovInput.addLovRelations(pageContext,    "TestItem" // base page item   
  48.                                            "DisplayItem2" // lov item   
  49.                                           LOV_PASSIVE_CRITERIA,  // direction   
  50.                                           LOV_REQUIRED_NO);   
  51.    
  52.    /*--------------------------------------------------创建LOV VO------------------------------------------------------*/   
  53.   ArrayList paramList =  new  ArrayList();  
  54.   String voName =  "FndUserLovVO2" ;  
  55.   String sql  =     "SELECT fu.user_id,"  +   
  56.                           "                fu.user_name,"  +   
  57.                           "                fu.start_date"  +   
  58.                           "    FROM fnd_user fu" ;  
  59.    
  60.    //paramList是用来创建LOV并在关联时都会用到的每个Item的Attribute   
  61.   paramList.add( new  String[]{ "UserId" "USER_ID" "oracle.jbo.domain.Number" null "Hide" null });  
  62.   paramList.add( new  String[]{ "UserName" "USER_NAME" "java.lang.String" "100" "Display" "SearchAllow" });  
  63.   paramList.add( new  String[]{ "StartDate" "START_DATE" "oracle.jbo.domain.Date" null "Display" null });  
  64.    //调用AM方法创建VO   
  65.   am.invokeMethod( "createVO" new  Serializable[]{voName, sql, paramList},  
  66.                              new  Class[]{String. class , String. class , paramList.getClass()});  
  67.    
  68.   am.getOADBTransaction().putTransientValue( "LovVOInstance" , voName);  
  69.   am.getOADBTransaction().putTransientValue( "LovAttribute" , paramList);  
  70.    
  71. }   


这是AM中创建VO的方法: 

  1. import  java.sql.Types;  
  2.    
  3. import  java.util.ArrayList;  
  4.    
  5. import  oracle.apps.fnd.framework.server.OAApplicationModuleImpl;  
  6. import  oracle.apps.fnd.framework.server.OADBTransaction;  
  7. import  oracle.apps.fnd.framework.server.OAViewDef;  
  8.    
  9. import  oracle.jbo.AttributeDef;  
  10.    
  11. public   void  createVO(String voName, String sql, ArrayList list){  
  12.     OADBTransaction dbtx = getOADBTransaction();  
  13.     String[] attribute =  new  String[ 6 ];  
  14.      int  types = - 9999 ;  
  15.     OAViewDef viewDef = dbtx.createViewDef();  
  16.    
  17.     viewDef.setSql(sql);  
  18.     viewDef.setExpertMode( true );  
  19.     viewDef.setViewObjectClass( "oracle.apps.fnd.framework.server.OAViewObjectImpl" );  
  20.     viewDef.setViewRowClass( "oracle.apps.fnd.framework.server.OAViewRowImpl" );  
  21.    
  22.      for ( int  i =  ; i < list.size(); i++){  
  23.         attribute = (String[])list.get(i);  
  24.          if ( "java.lang.String" .equals(attribute[ 2 ])){  
  25.             types = Types.VARCHAR;  
  26.         }  
  27.          else   if ( "oracle.jbo.domain.Number" .equals(attribute[ 2 ])){  
  28.             types = Types.NUMERIC;  
  29.         }  
  30.          else   if ( "oracle.jbo.domain.Date" .equals(attribute[ 2 ])){  
  31.             types = Types.DATE;  
  32.         }  
  33.    
  34.          if ( "java.lang.String" .equals(attribute[ 2 ])){  
  35.             viewDef.addSqlDerivedAttrDef(   attribute[ ],   
  36.                                             attribute[ 1 ],   
  37.                                             attribute[ 2 ],   
  38.                                             types,  
  39.                                              false ,  
  40.                                              true ,  
  41.                                             AttributeDef.UPDATEABLE,  
  42.                                             Integer.parseInt(attribute[ 3 ]));  
  43.         }  
  44.          else {  
  45.             viewDef.addSqlDerivedAttrDef(   attribute[ ],  
  46.                                             attribute[ 1 ],   
  47.                                             attribute[ 2 ],   
  48.                                             types,  
  49.                                              false ,  
  50.                                              true ,  
  51.                                             AttributeDef.UPDATEABLE);            }  
  52.     }  
  53.    
  54.      if (findViewObject(voName) !=  null ){  
  55.         findViewObject(voName).remove();  
  56.     }  
  57.    
  58.     createViewObject(voName, viewDef);  
  59. }   


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


  1. public   void  processRequest(OAPageContext pageContext, OAWebBean webBean)  
  2. {  
  3.    super .processRequest(pageContext, webBean);  
  4.   OAApplicationModule am = pageContext.getApplicationModule(webBean);  
  5.    
  6.   String voInstance   = (String)am.getOADBTransaction().getTransientValue( "LovVOInstance" );  
  7.   ArrayList paramList = (ArrayList)am.getOADBTransaction().getTransientValue( "LovAttribute" );  
  8.   String[] attribute  =  new  String[ 6 ];  
  9.    int  dispalyIndex    =  1 ;  
  10.    int  hideIndex       =  1 ;  
  11.    
  12.    //关联VO   
  13.   ((OAListOfValuesBean)webBean).setViewUsageName(voInstance);     
  14.    
  15.    //将Region中的MessageStyledText都设置为不显示   
  16.    for ( int  i= 1 ; i<= 5 ; i++){  
  17.     OAMessageStyledTextBean displayItem =  
  18.         (OAMessageStyledTextBean)webBean.findChildRecursive("DisplayItem"+i);  
  19.     displayItem.setRendered( false );  
  20.   }  
  21.    
  22.    //将Region中的FormValue都设置为不显示   
  23.    for ( int  i= 1 ; i<= 5 ; i++){  
  24.     OAFormValueBean hideItem =  
  25.         (OAFormValueBean)webBean.findChildRecursive("FormVal"+i);  
  26.     hideItem.setRendered( false );  
  27.   }  
  28.    
  29.    for ( int  i= ; i<paramList.size(); i++){  
  30.       attribute = (String[])paramList.get(i);  
  31.        if (attribute[ 4 ] !=  null  && "Display".equals(attribute[ 4 ])){  
  32.           OAMessageStyledTextBean displayItem =   
  33.               (OAMessageStyledTextBean)webBean.findChildRecursive("DisplayItem"+dispalyIndex);  
  34.    
  35.            //关联View Attribute   
  36.           displayItem.setViewAttributeName(attribute[ ]);  
  37.    
  38.            //设置Data Type   
  39.            if ("java.lang.String".equals(attribute[ 2 ])){  
  40.               displayItem.setDataType("VARCHAR2");  
  41.           }  
  42.            else   if ("oracle.jbo.domain.Number".equals(attribute[ 2 ])){  
  43.               displayItem.setDataType("NUMBER");  
  44.           }  
  45.            else   if ("oracle.jbo.domain.Date".equals(attribute[ 2 ])){  
  46.               displayItem.setDataType("DATE");  
  47.           }  
  48.            //设置显示   
  49.           displayItem.setRendered( true );  
  50.    
  51.            //是否可查询   
  52.            if (attribute[ 5 ] !=  null  && "SearchAllow".equals(attribute[ 5 ])){  
  53.               displayItem.setQueryable( true );  
  54.           }  
  55.    
  56.           dispalyIndex++;  
  57.       }  
  58.        else   if (attribute[ 4 ] !=  null  && "Hide".equals(attribute[ 4 ])){  
  59.           OAFormValueBean hideItem =   
  60.               (OAFormValueBean)webBean.findChildRecursive("FormVal"+hideIndex);  
  61.    
  62.            //hideItem.setViewUsageName("FndUserLovVO2");   
  63.           hideItem.setViewAttributeName(attribute[ ]);  
  64.    
  65.            if ("java.lang.String".equals(attribute[ 2 ])){  
  66.               hideItem.setDataType("VARCHAR2");  
  67.           }  
  68.            else   if ("oracle.jbo.domain.Number".equals(attribute[ 2 ])){  
  69.               hideItem.setDataType("NUMBER");  
  70.           }  
  71.            else   if ("oracle.jbo.domain.Date".equals(attribute[ 2 ])){  
  72.               hideItem.setDataType("DATE");  
  73.           }  
  74.    
  75.           hideItem.setRendered( true );  
  76.    
  77.           hideIndex++;  
  78.       }  
  79.   }  
  80. }   


由于是测试页面,所以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属性必须为空(否则会报错)。 

来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/24627116/viewspace-2653953/,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2010-11-17

  • 博文量
    166
  • 访问量
    364182