学习新Ajax技术--Dynamic Faces
引言: 读此篇文章时,假设您已经具备了 JavaServer Faces Technology 的基础知识.本文从Dynamic Faces所提供的一个例子出发.
Backing Bean
FruitInfoBean .java
package
simpleDynamicFaces;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
public class FruitInfoBean {
/** Creates a new instance of FruitInfoBean */
private Map < Object, Object > fruitNamesMap = new HashMap < Object, Object > ();
private String fruit = null ;
private String variety = null ;
private String varietyInfo = null ;
public FruitInfoBean() {
this .init();
}
private void init() {
FacesContext context = FacesContext.getCurrentInstance();
System.out.println( " Locale: " + context.getViewRoot().getLocale());
fruit = " Pear " ;
variety = " Aurora " ;
fruitNamesMap.put( " Pear " , " Aurora,Bartlet,Bosc,Comice,Delicious " );
fruitNamesMap.put( " Apple " , " Adanac,Akane,Ballarat,Braeburn,Fuji,Gala " );
fruitNamesMap.put( " Orange " , " Berna,Hamlin,Moro,Navel,Valencia " );
fruitNamesMap.put( " Peach " ,
" Brighton,Clingstone,Contender,Eden,Freestone " );
}
/*
* Handler method called when user selects a variety from the menu. This
* method updates the variety component model value and sets the varietyInfo
* model value to the appropriate message.
*/
public String updateVariety(ValueChangeEvent e) {
String newVariety = (String) e.getNewValue();
String currentFruit = getFruit();
setVarietyInfo( " Information updated: " + newVariety + " Old: "
+ currentFruit);
return null ;
}
public String getFruit() {
return this .fruit;
}
public void setFruit(String fruit) {
this .fruit = fruit;
}
protected ArrayList < SelectItem > fruits = null ;
public ArrayList < SelectItem > getFruits() {
fruits = new ArrayList < SelectItem > ();
fruits.add( new SelectItem( " Pear " , " Pear " ));
fruits.add( new SelectItem( " Apple " , " Apple " ));
fruits.add( new SelectItem( " Orange " , " Orange " ));
fruits.add( new SelectItem( " Peach " , " Peach " ));
return fruits;
}
public String getVariety() {
return this .variety;
}
public void setVariety(String variety) {
this .variety = variety;
}
protected ArrayList < SelectItem > varieties = null ;
public ArrayList < SelectItem > getVarieties() {
varieties = new ArrayList < SelectItem > ();
String[] fruitVarieties = fruitNamesMap.get( this .fruit).toString()
.split( " , " );
for ( int i = 0 ; i < fruitVarieties.length; i ++ ) {
varieties.add( new SelectItem(fruitVarieties[i], fruitVarieties[i]));
}
return varieties;
}
/*
* Handler method for the event of selecting a fruit. This method sets the
* model value for the variety component and sets the varietyInfo model
* value to the appropriate message.
*/
public void changeFruit(ValueChangeEvent e) {
String fruitValue = (String) e.getNewValue();
String[] varieties = fruitNamesMap.get(fruitValue).toString()
.split( " , " );
setVarietyInfo( " Information: " + (varieties[ 0 ]));
setVariety(varieties[ 0 ]);
}
public String getVarietyInfo() {
return this .varietyInfo;
}
public void setVarietyInfo(String varietyInfo) {
this .varietyInfo = varietyInfo;
}
/*
* The following code is used with the installDeferredAjaxTransaction use
* case
*/
private String fruitQuiz = null ;
public String getFruitQuiz() {
return this .fruitQuiz;
}
public void setFruitQuiz(String fruit) {
this .fruitQuiz = fruit;
}
}
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;
public class FruitInfoBean {
/** Creates a new instance of FruitInfoBean */
private Map < Object, Object > fruitNamesMap = new HashMap < Object, Object > ();
private String fruit = null ;
private String variety = null ;
private String varietyInfo = null ;
public FruitInfoBean() {
this .init();
}
private void init() {
FacesContext context = FacesContext.getCurrentInstance();
System.out.println( " Locale: " + context.getViewRoot().getLocale());
fruit = " Pear " ;
variety = " Aurora " ;
fruitNamesMap.put( " Pear " , " Aurora,Bartlet,Bosc,Comice,Delicious " );
fruitNamesMap.put( " Apple " , " Adanac,Akane,Ballarat,Braeburn,Fuji,Gala " );
fruitNamesMap.put( " Orange " , " Berna,Hamlin,Moro,Navel,Valencia " );
fruitNamesMap.put( " Peach " ,
" Brighton,Clingstone,Contender,Eden,Freestone " );
}
/*
* Handler method called when user selects a variety from the menu. This
* method updates the variety component model value and sets the varietyInfo
* model value to the appropriate message.
*/
public String updateVariety(ValueChangeEvent e) {
String newVariety = (String) e.getNewValue();
String currentFruit = getFruit();
setVarietyInfo( " Information updated: " + newVariety + " Old: "
+ currentFruit);
return null ;
}
public String getFruit() {
return this .fruit;
}
public void setFruit(String fruit) {
this .fruit = fruit;
}
protected ArrayList < SelectItem > fruits = null ;
public ArrayList < SelectItem > getFruits() {
fruits = new ArrayList < SelectItem > ();
fruits.add( new SelectItem( " Pear " , " Pear " ));
fruits.add( new SelectItem( " Apple " , " Apple " ));
fruits.add( new SelectItem( " Orange " , " Orange " ));
fruits.add( new SelectItem( " Peach " , " Peach " ));
return fruits;
}
public String getVariety() {
return this .variety;
}
public void setVariety(String variety) {
this .variety = variety;
}
protected ArrayList < SelectItem > varieties = null ;
public ArrayList < SelectItem > getVarieties() {
varieties = new ArrayList < SelectItem > ();
String[] fruitVarieties = fruitNamesMap.get( this .fruit).toString()
.split( " , " );
for ( int i = 0 ; i < fruitVarieties.length; i ++ ) {
varieties.add( new SelectItem(fruitVarieties[i], fruitVarieties[i]));
}
return varieties;
}
/*
* Handler method for the event of selecting a fruit. This method sets the
* model value for the variety component and sets the varietyInfo model
* value to the appropriate message.
*/
public void changeFruit(ValueChangeEvent e) {
String fruitValue = (String) e.getNewValue();
String[] varieties = fruitNamesMap.get(fruitValue).toString()
.split( " , " );
setVarietyInfo( " Information: " + (varieties[ 0 ]));
setVariety(varieties[ 0 ]);
}
public String getVarietyInfo() {
return this .varietyInfo;
}
public void setVarietyInfo(String varietyInfo) {
this .varietyInfo = varietyInfo;
}
/*
* The following code is used with the installDeferredAjaxTransaction use
* case
*/
private String fruitQuiz = null ;
public String getFruitQuiz() {
return this .fruitQuiz;
}
public void setFruitQuiz(String fruit) {
this .fruitQuiz = fruit;
}
}
fireAjaxTx.jsp
<!
DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd" >
< %@ taglib uri ="http://java.sun.com/jsf/core" prefix ="f" % >
< %@ taglib uri ="http://java.sun.com/jsf/html" prefix ="h" % >
< %@ taglib prefix ="jsfExt" uri ="http://java.sun.com/jsf/extensions/dynafaces" % >
< f:view >
< html >
< head >
< title > Fruit Varieties </ title >
< jsfExt:scripts />
</ head >
< body bgcolor ="white" >
< h:form prependId ="false" id ="form" >
< h1 > Fruit Varieties </ h1 >
< h:panelGrid columns ="2" cellpadding ="4" >
< h:outputText value ="Select a fruit:" />
< h:outputText value ="Select a variety:" />
< h:selectOneRadio id ="fruit" value ="#{fruitInfoBean.fruit}"
onclick ="DynaFaces.fireAjaxTransaction(this, { execute: 'fruit'});"
valueChangeListener ="#{fruitInfoBean.changeFruit}" >
< f:selectItems value ="#{fruitInfoBean.fruits}" />
</ h:selectOneRadio >
< h:selectOneMenu id ="variety" value ="#{fruitInfoBean.variety}"
onchange ="DynaFaces.fireAjaxTransaction(this, { execute: 'variety' });"
valueChangeListener ="#{fruitInfoBean.updateVariety}" >
< f:selectItems value ="#{fruitInfoBean.varieties}" />
</ h:selectOneMenu >
</ h:panelGrid >
< h:outputText id ="varietyInfo" value ="#{fruitInfoBean.varietyInfo}" />
</ h:form >
</ body >
</ html >
</ f:view >
"http://www.w3.org/TR/html4/loose.dtd" >
< %@ taglib uri ="http://java.sun.com/jsf/core" prefix ="f" % >
< %@ taglib uri ="http://java.sun.com/jsf/html" prefix ="h" % >
< %@ taglib prefix ="jsfExt" uri ="http://java.sun.com/jsf/extensions/dynafaces" % >
< f:view >
< html >
< head >
< title > Fruit Varieties </ title >
< jsfExt:scripts />
</ head >
< body bgcolor ="white" >
< h:form prependId ="false" id ="form" >
< h1 > Fruit Varieties </ h1 >
< h:panelGrid columns ="2" cellpadding ="4" >
< h:outputText value ="Select a fruit:" />
< h:outputText value ="Select a variety:" />
< h:selectOneRadio id ="fruit" value ="#{fruitInfoBean.fruit}"
onclick ="DynaFaces.fireAjaxTransaction(this, { execute: 'fruit'});"
valueChangeListener ="#{fruitInfoBean.changeFruit}" >
< f:selectItems value ="#{fruitInfoBean.fruits}" />
</ h:selectOneRadio >
< h:selectOneMenu id ="variety" value ="#{fruitInfoBean.variety}"
onchange ="DynaFaces.fireAjaxTransaction(this, { execute: 'variety' });"
valueChangeListener ="#{fruitInfoBean.updateVariety}" >
< f:selectItems value ="#{fruitInfoBean.varieties}" />
</ h:selectOneMenu >
</ h:panelGrid >
< h:outputText id ="varietyInfo" value ="#{fruitInfoBean.varietyInfo}" />
</ h:form >
</ body >
</ html >
</ f:view >
其中的 DynaFaces.
fireAjaxTransaction
方法由jsf-extensions-dynamic-faces.jar里的com_sun
_
faces_ajax.js定义,这个方法可以在JSF组件级别上执行AJAX异步更新.
使用fireAjaxTransaction:1.在JSF组件的标签里加JavaScript 事件属性,如:onClick="DynaFaces.fireAjaxTransaction(paras)"
2. 在DynaFaces.fireAjaxTransaction加上paras,以便可以传递一些参数到Server.
execute: 'fruit'的意思是:Id为
fruit的JSF组件(包括这个组件的所有Children),将
会
Go Through JSF Life Circle的
execute
部分.
在这部分生命周期后,当前页面所有
的
JSF组件将会通过
Ajax
被
re-render(
这里是默认行为,
因为没有指定render属性
),
其中execute生命周期部分所做的工作如下:转换和验证数据,更新数据模型和处理Action事件.
value-change
事件属于
fruit
组件,所以当发出
AJAX
请求时,该事件也会被处理,从而达到更新模型数据的目的.
常用的属性:
1. execute: A JavaScript String specifying which JSF component id's to process.
2. immediate: Not really needed, but if there was validation on the field in "execute" immediate would skip the validation.
3. inputs: The values sent to the server. This may be different than the components processed.
4. render: This specifies which area(s) of the screen should be updated with the response. In this case the < div > around our message text.
2. immediate: Not really needed, but if there was validation on the field in "execute" immediate would skip the validation.
3. inputs: The values sent to the server. This may be different than the components processed.
4. render: This specifies which area(s) of the screen should be updated with the response. In this case the < div > around our message text.
所需的Lib如下:
有关Dynamic Faces的包可以从这里下载: https://jsf-extensions.dev.java.net/servlets/ProjectDocumentList