何时使用valueChangeListener或f:ajax监听器?

以下两段代码之间有什么区别 – 关于listener位置?

 <h:selectOneMenu ...> <f:selectItems ... /> <f:ajax listener="#{bean.listener}" /> </h:selectOneMenu> 

 <h:selectOneMenu ... valueChangeListener="#{bean.listener}"> <f:selectItems ... /> </h:selectOneMenu> 

valueChangeListener只会在表单提交时被调用, 并且提交的值与初始值不同。 因此, 只有 HTML DOM change事件被触发时才会被调用。 如果您希望在HTML DOM change事件期间提交表单,那么您需要添加另一个<f:ajax/>而没有侦听器(!)到input组件。 它会导致一个表单提交哪个进程只处理当前的组件(如execute="@this" )。

 <h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}"> <f:selectItems ... /> <f:ajax /> </h:selectOneMenu> 

当使用<f:ajax listener>而不是valueChangeListener ,它将在HTML DOM change事件过程中默认执行。 在表示checkbox或单选button的UICommand组件和input组件内部,它将仅在HTML DOM click事件期间默认执行。

 <h:selectOneMenu value="#{bean.value}"> <f:selectItems ... /> <f:ajax listener="#{bean.ajaxListener}" /> </h:selectOneMenu> 

另一个主要区别是在PROCESS_VALIDATIONS阶段结束时调用valueChangeListener方法。 此时,提交的值尚未在模型中更新。 所以你不能通过访问绑定到input组件value的bean属性来获取它。 你需要通过ValueChangeEvent#getNewValue()来获取它。 ValueChangeEvent#getOldValue()方法也可以使用旧值。

 public void changeListener(ValueChangeEvent event) { Object oldValue = event.getOldValue(); Object newValue = event.getNewValue(); // ... } 

INVOKE_APPLICATION阶段调用<f:ajax listener>方法。 此时,提交的值已经在模型中更新。 您可以通过直接访问绑定到input组件value的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 。 也就是说,你实际上对旧价值和新价值感兴趣(例如logging它们)。

 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 // ... } 

对于第一个片段(ajax listener属性):

ajax标签的“listener”属性是每次在客户端发生ajax函数时在服务器端调用的方法。 例如,你可以使用这个属性来指定一个服务器端函数,每当用户按下一个键时调用

但第二个片段(valueChangeListener):

ValueChangeListener只会在表单提交时调用,而不是在input值改变时调用

*您可能想查看这个方便的答案