2012年5月3日星期四

ADF_119:如何通过程序触发按钮上的Action事件?

开发环境:JDevloper 11.1.2.1.0+ Oracle Database 10g Express Edition 10.2.0.1。

这个问题来自于https://cn.forums.oracle.com/forums/thread.jspa?threadID=2373947。
我觉得这个问题比较典型,实际使用中可能会用到,因此做了个实验总结了一下。

我在《传递参数给TaskFlow》项目的基础上,修改了department.jsf页面代码,增加了一个按钮以及相应的Managed Bean。
其中,CommandLink的代码如下:
<af:commandLink text="#{row.DepartmentId}" id="cl1" action="#{myBackingBean.selectLink_action}">
<af:setPropertyListener from="#{row.DepartmentId}" to="#{requestScope.deptId}" type="action"/>
<af:setPropertyListener from="#{row.DepartmentId}" to="#{pageFlowScope.pf_deptId}" type="action"/>
</af:commandLink>

CommandButton的代码如下:
<af:commandButton text="Select Department" id="cb1" actionListener="#{myBackingBean.selectButton_actionListener}"/>

场景1:点击CommandButton,然后触发CommandLink的Action事件,即相当于点击了CommandLink。
(1)CommandLink上的Action代码如下:
public String selectLink_action() {
FacesContext fctx = FacesContext.getCurrentInstance();
UIViewRoot root = fctx.getViewRoot();
RichCommandButton rcb = (RichCommandButton)root.findComponent("cb1");
System.out.println("#################### " + rcb);

ADFContext ac = ADFContext.getCurrent();
Map requestScope = ac.getRequestScope();
Map pageFlowScope = ac.getPageFlowScope();
requestScope.put("deptId", JSFUtils.getManagedBeanValue("bindings.DepartmentId.inputValue"));
pageFlowScope.put("pf_deptId", JSFUtils.getManagedBeanValue("bindings.DepartmentId.inputValue"));

return "toEmployees";
}
注意,之所以在这里要给RequestScope和PageFlowScope变量重新赋值,是因为通过程序无法触发setPropertyListener。

(2)CommandButton上的Action代码如下:
public void selectButton_actionListener(ActionEvent evt) {
RichCommandButton rcb = (RichCommandButton)evt.getSource();
RichCommandLink rcl = (RichCommandLink)rcb.findComponent("t1:cl1");
ActionEvent actionEvent = new ActionEvent(rcl);
actionEvent.queue();
}
其原理是:找到CommandLink对象,为其创建一个ActionEvent事件,并压入事件队列。
这样就相当于触发了CommandLink的Action事件。

场景2:点击CommandLink,然后触发CommandButton的Action事件,即相当于点击了CommandButton。
(1)CommandLink上的Action代码如下:
public String selectLink_action() {
FacesContext fctx = FacesContext.getCurrentInstance();
UIViewRoot root = fctx.getViewRoot();
RichCommandButton rcb = (RichCommandButton)root.findComponent("cb1");
ActionEvent actionEvent = new ActionEvent(rcb);
actionEvent.queue();
return "toEmployees";
}
其原理是:找到CommandButton对象,为其创建一个ActionEvent事件,并压入事件队列。
这样就相当于触发了CommandButton的Action事件。

(2)CommandButton上的Action代码如下:
public void selectButton_actionListener(ActionEvent evt) {
ADFContext ac = ADFContext.getCurrent();
Map requestScope = ac.getRequestScope();
System.out.println("#################### " + requestScope.get("deptId"));
Map pageFlowScope = ac.getPageFlowScope();
System.out.println("#################### " + pageFlowScope.get("pf_deptId"));
}
因为在CommandLink中已经使用SetPropertyListener为RequestScope和PageFlowScope变量赋值了,这里只是获取这些变量,并打印出来。

场景3:点击CommandLink,然后通过ClientListener触发CommandButton的Action事件,即相当于点击了CommandButton。
场景3与场景2是一样的,不过实现方式不同,场景3是通过ClientListener调用JavaScript函数实现的。
(1)修改department.jsf页面,为CommandLink增加ClientListener及相应的JavaScript函数。
JavaScript 函数:
<af:resource type="javascript">
function clickOnCommandLink(evt) {
var cmdButton = AdfPage.PAGE.findComponentByAbsoluteId("cb1");
AdfActionEvent.queue(cmdButton, cmdButton.getPartialSubmit());
}
</af:resource>
其原理是:找到CommandButton对象,然后为其压入一个ActionEvent到事件队列中。

CommandLink代码:
<af:commandLink text="#{row.DepartmentId}" id="cl1" action="#{myBackingBean.selectLink_action}">
<af:setPropertyListener from="#{row.DepartmentId}" to="#{requestScope.deptId}" type="action"/>
<af:setPropertyListener from="#{row.DepartmentId}" to="#{pageFlowScope.pf_deptId}"
type="action"/>
<af:clientListener type="click" method="clickOnCommandLink"/>
</af:commandLink>

(2)Managed Bean代码修改如下:
CommandLink的Action事件,因为已经通过JavaScript函数触发CommandButton上的事件了,这里只要返回导航String就可以了。
public String selectLink_action() {
return "toEmployees";
}
CommandButton的Action Listener的代码不变:
public void selectButton_actionListener(ActionEvent evt) {
ADFContext ac = ADFContext.getCurrent();
Map requestScope = ac.getRequestScope();
System.out.println("#################### " + requestScope.get("deptId"));
Map pageFlowScope = ac.getPageFlowScope();
System.out.println("#################### " + pageFlowScope.get("pf_deptId"));
}

Project 下载:ADF_TaskFlow_InputParam(Trigger ActionEvent).7z

参考文献:
1. http://jjzheng.blogspot.com/2011/06/invoke-actions-on-non-command-component.html

没有评论: