|
增强的事件机制
1. 前言众所周知,JSF的事件机制借鉴了AWT和Swing的事件模型。熟悉AWT或Swing的同学知道,AWT和Swing的事件模型有一个很好的设计:为不同的事件侦听方法提供了不同的事件上下文,如对于鼠标事件侦听器的对应方法,有
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
用户可以从MouseEvent中方便得获取上下文信息,其他动作事件键盘事件也有相应的事件上下文。而在OperaMasks SDK中,通过 ajax:action 构件,同样支持鼠标动作键盘动作等等调用后台方法,那么,OperaMasks SDK的事件机制是否能做到像AWT和Swing那样提供丰富的事件上下文呢?事实上,在2.3版本中,OperaMasks SDK不仅做到了,而且可以说在一些方面做得比AWT和Swing更好,或者说,更适合Web程序。 OperaMasks 2.3版本定义了一个接口 AjaxActionSupport,如果触发事件的构件实现了 AjaxActionSupport 接口,那么该构件的事件处理将有一些新特性。2.3 版本中实现了 AjaxActionSupport 接口的构件有
下面是上述构件事件处理的新特性 2.1. 丰富的事件上下文OperaMasks 2.3 新增了事件上下文支持。举个例子:在2.3之前的版本中,如果要响应 w:tree 的 onclick 事件并获取点击的节点的文本内容,页面如下 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE HTML PUBLIC "" ""> <f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout" xmlns:h="http://java.sun.com/jsf/html" xmlns:ajax="http://www.apusic.com/jsf/ajax" renderKitId="AJAX"> <w:head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> </w:head> <w:page title="Insert title here"> <w:tree id="tree"> <w:treeNode text="root"></w:treeNode> </w:tree> </w:page> </f:view> 对应的 LiteBean 需要这么写 @Bind UITree tree; 现在后台LiteBean可以这么写
@Action
public void tree_onclick(TreeNodeEvent event) {
System.out.println(event.getEventNode().getText());
上述例子的执行结果如下 下面是一些常用的事件及对应的事件上下文 Table 1. 一些构件的事件及对应的事件上下文
现在我们知道,一些事件的处理方法有特定的事件上下文来获取信息,那么对于更多的事件呢?例如在一些情况下,我们需要获取触发事件的构件,这个需求能否满足呢?答案肯定的。2.3版本中定义了一个 AjaxActionEvent 的事件上下文类,这个类是上表中所有事件上下文的父类,所有的事件处理方法都可用这个类作为参数,如响应 w:textField 的 onblur 事件时,可以这么写
public void field_onblur(AjaxActionEvent event) {
event.getTargetComponent(); // 获取事件源构件
}
AjaxActionEvent 类提供了三个常用方法,如下
关于传递参数在后面进行说明。 从上面我们可知,事件对应的方法签名可以有两种或三种,如对于以下页面
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HTML PUBLIC "" "">
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ajax="http://www.apusic.com/jsf/ajax"
renderKitId="AJAX">
<w:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</w:head>
<w:page title="Insert title here">
<w:form>
<w:textField>
<ajax:action event="onchange" action="#{fieldBean.field_onchange }"></ajax:action>
</w:textField>
</w:form>
</w:page>
</f:view>
LiteBean中响应方法的签名可以是以下三种签名的任意一种
public void field_onchange() {
System.out.println("field_onchange() executed!");
}
public void field_onchange(AjaxActionEvent event) {
System.out.println("field_onchange(AjaxActionEvent event) executed!");
}
public void field_onchange(FieldChangeEvent event) {
System.out.println("field_onchange(FieldChangeEvent event) executed!");
}
但是,如果这三个方法同时出现了,这些方法会都执行吗?这就要涉及自动匹配最佳方法这个有趣的特性了。在上面例子中,当后台出现这几个方法时,签名为 field_onchange(FieldChangeEvent event) 的方法将会被调用,其他方法不会被调用。OperaMasks SDK中对事件方法的查找顺序如下:先查找参数为特定的事件上下文的方法(如field_onchange(FieldChangeEvent event)),如存在即执行;否则继续查找参数为 AjaxActionEvent 的方法(如field_onchange(AjaxActionEvent event) ),如存在即执行;否则继续查找无参的方法(如field_onchange()),如存在即执行,否则抛出找不到指定方法的异常。上面例子的执行结果如下 ![]() Figure 2. 自动匹配最佳方法例子运行结果
除了使用EL方式和IoVC方式为构件添加侦听器外,2.3还支持动态添加侦听器,如下
@Bind
private UITextField txt;
public void txt_onchange(AjaxActionEvent e){
// do something here
}
@BeforeRender
public void beforeRender(boolean isPostback){
if(!isPostback){
txt.getAjaxEventHandler().addELBinding("onchange", "#{bean.txt_onchange}", false);
其中, getAjaxEventHandler() 方法为 AjaxActionSupport 接口定义的方法。 2.4. 传递自定义参数虽然OperaMasks SDK的事件机制提供了一些事件上下文,但是对于WEB来说,我们需要许多的参数,SDK提供的事件上下文不一定够用,我们可能需要传递一些自定义参数,如何解决呢?用隐藏 input 传递参数吗?可以,但实在太土了,我们可以用 2.3 提供的 ajax:param 构件传递自定义参数,如下
<w:form>
<w:textField>
<ajax:action event="onblur" action="#{bean.field_onblur}">
<ajax:param name="company" value="apusic"></ajax:param>
</ajax:action>
</w:textField>
</w:form>
这里可能有人会问,看起来这个 ajax:param 与 f:param 并无不同,为何要重造一个轮子呢?这个 ajax:param 其实还有一个特别之处,那就是它的值可以是 Javascript 变量(或者说,Javascript表达式)。如下,w:textField 构件在 onblur 事件发生时同时发送自身的值作为参数
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE HTML PUBLIC "" "">
<f:view xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core"
xmlns:w="http://www.apusic.com/jsf/widget" xmlns:layout="http://www.apusic.com/jsf/layout"
xmlns:h="http://java.sun.com/jsf/html" xmlns:ajax="http://www.apusic.com/jsf/ajax"
renderKitId="AJAX">
<w:head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</w:head>
<w:page title="Insert title here">
<w:form>
<w:textField>
<ajax:action event="onblur" action="#{txtBean.txt_onblur }">
<ajax:param name="fieldValue" value="arguments[0].getValue()"
后台LiteBean对应方法为
public void txt_onblur(AjaxActionEvent event) {
System.out.println(event.getParameter("fieldValue"));
}
运行上述例子,访问页面,输入"operamasks"并切换焦点 后台打印如下 ![]() Figure 4. ajax:param例子运行结果 当然,这儿的 ajax:param 传递的Javascript参数值最好是boolean, number, string等基本类型,不然,后台获取的值就是Javascript变量调用 toString() 方法后的值。 OperaMasks 2.3版本不仅提供了一系列的新特性,还支持了一些以往欠缺的事件,如Field构件的key事件支持和DataGrid的cellselect事件支持。用过 w:dataGrid 构件的同学可能有过这样的经历,在一个 selectionModel 属性设置为 CellSelectModel 的 w:dataGrid 中,如果先响应用户的 cellselect 事件,很难做到。在 2.3 中,这个不再是问题,如下
<w:dataGrid selectionModel="#{new org.operamasks.faces.component.grid.CellSelectionModel()}">
<ajax:action event="oncellselect" action="#{bean.grid_oncellselect}">
</ajax:action>
</w:dataGrid>
public void grid_oncellselect(CellSelectEvent event) {
event.getRowIndex();
event.getColIndex();
OperaMasks 2.3的事件机制介绍到此告一段落,更多内容,可参考OperaMasks在线文档。
所有评论
mfkvfn
2009-12-24
评论道:
在发送请求之前,计算arguments[0].getValue()的值,然后为ajax:action发送的Ajax请求中添加此参数。然后在ajax:action组件的decode时以ajax:action和它所有的ajax:param子组件的值来构造一个AjaxActionEvent。然后广播事件。当事件监听时执行到public void txt_onblur(AjaxActionEvent event)方法的event.getParameter("fieldValue")时直接从AjaxActionEvent的params这个Map中取得value值就可以了。
风的选择
2009-11-02
评论道:
我想问一下
1 共1页
您还没有登录,请登录后发表评论
|
相关文章
|
@Action
public void tree_onclick() {
System.out.println(tree.getEventNode().getText());
}


