<h:selectOneMenu ...>
<f:selectItems ... />
<f:ajax listener="#{bean.listener}" />
</h:selectOneMenu>
和
<h:selectOneMenu ... valuechangelistener="#{bean.listener}">
<f:selectItems ... />
</h:selectOneMenu>
<h:selectOneMenu value="#{bean.value}" valuechangelistener="#{bean.changelistener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
当使用< f:ajax listener>而不是valuechangelistener,它将默认在HTML DOM更改事件期间已执行。在UICommand组件和表示复选框或单选按钮的输入组件的内部,它将默认在HTML DOM点击事件期间执行。
<h:selectOneMenu value="#{bean.value}">
<f:selectItems ... />
<f:ajax listener="#{bean.ajaxListener}" />
</h:selectOneMenu>
另一个主要区别是在PROCESS_VALIDATIONS阶段结束时调用valuechangelistener方法。此时,提交的值尚未在模型中更新。所以你不能通过访问绑定到输入组件的值的bean属性来获得它。你需要通过ValueChangeEvent#getNewValue()获取它。旧的值也是可用的ValueChangeEvent#getoldValue()。
public void changelistener(ValueChangeEvent event) {
Object oldValue = event.getoldValue();
Object newValue = event.getNewValue();
// ...
}
< f:ajax listener>方法在INVOKE_APPLICATION阶段被调用。此时,已提交的值已在模型中更新。你可以通过直接访问绑定到输入组件的值的bean属性来获得它。
private Object value; // +getter+setter.
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value); // Look,(new) value is already set.
}
另外,如果您需要基于提交的值更新另一个属性,那么当您使用valuechangelistener时,它会失败,因为更新的属性可以在随后的UPDATE_MODEL_VALUES阶段期间被提交的值覆盖。这就是为什么你在旧的JSF 1.x应用程序/教程/资源中看到一个valuechangelistener在这样的结构中与immediate =“true”和FacesContext#renderResponse()结合使用来防止这种情况发生。毕竟,使用valuechangelistener来执行业务操作实际上总是一个黑客/解决方法。
总结:仅当需要截取实际值更改本身时,才使用valuechangelistener。也就是说你实际上对旧的和新的值感兴趣(例如,记录他们)。
public void changelistener(ValueChangeEvent event) {
changeLogger.log(event.getoldValue(),event.getNewValue());
}
使用< f:ajax listener>只有当您需要对新更改的值执行业务操作时。也就是说您实际上只对新值感兴趣(例如填充第二个下拉列表)。
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
如果您在执行业务操作时实际上对旧值感兴趣,则回退到valuechangelistener,但将其排队到INVOKE_APPLICATION阶段。
public void changelistener(ValueChangeEvent event) {
if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
event.setPhaseId(PhaseId.INVOKE_APPLICATION);
event.queue();
return;
}
Object oldValue = event.getoldValue();
Object newValue = event.getNewValue();
System.out.println(newValue.equals(value)); // true
// ...
}