Form技巧:如果在输入Item之后,可以自动执行GO_BLOCK等内置函数

来源:互联网 发布:广铁集团网络招聘 编辑:程序博客网 时间:2024/06/05 06:10

很多时候,我们想实现这样子的操作效果:

当向一个特定的Item输入数据之后,自动触发一系列的动作,例如GO_BLOCK,然后Loop这个Block,向这个Block维护一定的值(或者检查值)。这样子可以很大程度方便User操作(因为是自动操作的)

但是,众所周知,如果在WHEN-VALIDATE-ITEM等触发器用GO_BLOCK等导航的内置函数,会报错:FRM-40737存在非法的受限过程。因为验证的触发器是不可以导航到别的记录的(大部分触发器都不可以)

这里发现一个触发器可以达到这个效果:KEY-NEXT-ITEM

这个触发器KEY-NEXT-ITEM是当用户向对应的Item输入数据,然后点Tab按键或者Enter按键(当然,画面没有Enter就直接调用的按钮)的时候,会触发这个触发器。而这个触发器是可以随意做一些我们想做的动作。例如跳到别的Item,别的Block等等。

但是,用这个触发器的程序猿会发现,如果用户录入数据的导航方式不是:向特定的Item输入值之后,用键盘Tab(或者Enter)导航到下一个Item;而是用鼠标直接点击,那是触发不了KEY-NEXT-ITEM事件,从而导致程序有隐含的bug

怎么办?这里给出一个解决方案,虽然不是最好的,但是却是可以用的:对于这个Item,禁用鼠标导航的操作方式!

如何禁用?其原理:利用当用户点Tab按键的时候,触发器的顺序是:先触发KEY-NEXT-ITEM;再触发WHEN-VALIDATE-ITEM。当用户直接用鼠标导航的时候,只是触发WHEN-VALIDATE-ITEM。所以在WHEN-VALIDATE-ITEM下手即可,用RAISE FORM_TRIGGER_FAILURE;禁用。

实现步骤:

1 增加一个参数::PARAMETER.CURRENT_KEY_MODE。目的是为了区分用户的录入之后,导航的方式。

2 WHEN-VALIDATE-ITEM触发器直接写下面的代码:

Begin

---当有变更,而且CURRENT_KEY_MODE(输入之后的导航类型)不是KEY-NEXT-ITEM的时候,必须用tab按键或者enter导航!

       FND_MESSAGE.DEBUG('WHEN-VALIDATE-ITEM1');

IF :MDS_CONTROL.SCHEDULE_DATE IS NOT NULL AND NVL(:PARAMETER.CURRENT_KEY_MODE,'WHEN-VALIDATE-ITEM') <> 'KEY-NEXT-ITEM' THEN

FND_MESSAGE.SET_STRING('请注意:该栏位输入之后,请按Tab按键或者Enter按键导航!');

FND_MESSAGE.HINT;

RAISE FORM_TRIGGER_FAILURE;---禁止用户用鼠标点击导航!

  END IF;

       FND_MESSAGE.DEBUG('WHEN-VALIDATE-ITEM2');

End;

      

3 然后在KEY-NEXT-ITEM增加代码:

Declare

       l_cur_record Number;

Begin

       FND_MESSAGE.DEBUG('KEY-NEXT-ITEM1');

If :MDS_CONTROL.SCHEDULE_DATE Is Not Null Then

       :PARAMETER.CURRENT_KEY_MODE := 'KEY-NEXT-ITEM';

              Go_Block('XYG_MANUFACTURE_NEED');

              l_cur_record := :SYSTEM.cursor_record;

              First_Record;

              Loop

               

                     If Nvl(:XYG_MANUFACTURE_NEED.CHK,'N')='Y' AND NVL(:XYG_MANUFACTURE_NEED.SCHEDULE_DATE,SYSDATE) <> :MDS_CONTROL.SCHEDULE_DATE

                            AND NVL(:XYG_MANUFACTURE_NEED.PROCESS_STATUS,'N') = 'Y'  ---没审核的不可以预排

                              Then

                             :XYG_MANUFACTURE_NEED.SCHEDULE_DATE := :MDS_CONTROL.SCHEDULE_DATE;

                             ---2011-10-19 samt add

                             :XYG_MANUFACTURE_NEED.SCHEDULE_USER_ID := FND_GLOBAL.USER_ID;

                      :XYG_MANUFACTURE_NEED.SCHEDULE_USER :=SUBSTRB( XYG_PUB_COMMON_PKG.GET_FND_FULL_NAME(FND_GLOBAL.USER_ID,SYSDATE,0),1,240) ;--FND_GLOBAL.USER_NAME;

                     End If;

                     Exit When :SYSTEM.LAST_RECORD='TRUE';              

                     Next_Record;               

              End Loop;

               --:MDS_CONTROL.SCHEDULE_DATE  := NULL; ---清空

              Go_record(l_cur_record);

       :PARAMETER.CURRENT_KEY_MODE := 'WHEN-VALIDATE-ITEM';

End If;

       FND_MESSAGE.DEBUG('KEY-NEXT-ITEM2');

End;


----2014.9.26更新:

有个问题:

 form header block中的一个item值发生变化,自动删除 line block中的值,这个你一般怎么做的?

一个办法是:
先增加一个对应要核对头Item是否发生变化的判断Item,可以叫ITEM_COPY之类的,非数据块的。
在Key-commit的时候,再判断这个头的ITEM_COPY是否<>ITEM,如果是,则自动删除行的内容。
因为KEY-COMMIT是可以实现GO_BLOCK,清除BLOCK等动作。

 另外,在用户试图进入到行BLOCK的时候,如果头的ITEM_COPY是否<>ITEM,则提醒用户:这个ITEM的值发生变化了,请保存。
就可以实现这个效果了。

另外一个办法:
 还是增加一个ITEM_COPY(比对是否有做修改嘛,这个是必须的),然后在被修改的ITEM的WHEN-VALIDATE-ITEM触发器里面,判断是否值被修改(ITEM_COPY<>ITEM),如果是,则自动在数据库DELETE记录,并且标识一个有自动做了DELETE记录的标识(可以用PARAMETER做,要考虑多个头的数据行的切换的问题。)
然后当用户点到行Block的时候,系统判断上面的(是否有自动做了DELETE记录的标识),如果是=Y,则自动刷新行的BLOCK即可。
这样子的话,就可以完全防呆了,反正有做了修改,DB数据库一定会删除记录。只不过对于用户来说刷新动作晚了一点而已。 
其实可以给个提示
 当删掉行数据之后,直接提示:
您已经修改了这个值,系统已经在后台将行记录清空。请鼠标点到行块以确认数据。 

最后的办法:
这个办法是我这个帖子说的办法,但是不是很建议,因为这个办法阉割了用户用鼠标操作画面的操作模式。



原创粉丝点击