的
valueChangeListener形式被提交时将只被调用 和 提交的值是从初始值不同。因此, 仅
change触发HTML DOM
事件时不会调用它。如果您想在HTML DOM
change事件期间提交表单,则需要向
<f:ajax/>输入组件添加另一个没有listener(!)的表单。它将导致仅处理当前组件的表单提交(如中所述
execute="@this")。
<h:selectoneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}"> <f:selectItems ... /> <f:ajax /></h:selectOneMenu>当使用
<f:ajax listener>代替时
valueChangeListener,默认情况下它将在HTML DOM
change事件期间执行。在
UICommand表示复选框或单选按钮的组件和输入组件内部,默认情况下将
click仅在HTML DOM
事件期间执行该组件。
<h:selectoneMenu value="#{bean.value}"> <f:selectItems ... /> <f:ajax listener="#{bean.ajaxListener}" /></h:selectOneMenu>另一个主要区别是该
valueChangeListener方法在
PROCESS_VALIDATIONS阶段结束时被调用。那时,提交的值尚未在模型中更新。因此,仅通过访问绑定到输入组件的bean属性就无法获得它
value。您需要通过
ValueChangeEvent#getNewValue()。顺便提一下,旧值也可以使用
ValueChangeEvent#getOldValue()。
public void changeListener(ValueChangeEvent event) { Object oldValue = event.getOldValue(); Object newValue = event.getNewValue(); // ...}该
<f:ajaxlistener>方法在
INVOKE_APPLICATION阶段中被调用。那时,提交的值已在模型中更新。您可以通过直接访问绑定到输入组件的bean属性来获取它
value。
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这样的结构中的a
与结合使用
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 // ...}


