Dan*_*jel 83 ajax jsf listener valuechangelistener jsf-2
以下两段代码之间有什么区别 - 关于listener
放置?
<h:selectOneMenu ...>
<f:selectItems ... />
<f:ajax listener="#{bean.listener}" />
</h:selectOneMenu>
Run Code Online (Sandbox Code Playgroud)
和
<h:selectOneMenu ... valueChangeListener="#{bean.listener}">
<f:selectItems ... />
</h:selectOneMenu>
Run Code Online (Sandbox Code Playgroud)
Bal*_*usC 178
的valueChangeListener
形式被提交时将只被调用和提交的值是从初始值不同.因此,仅change
触发HTML DOM 事件时不会调用它.如果您想在HTML DOM change
事件期间提交表单,那么您需要<f:ajax/>
在输入组件中添加另一个没有监听器(!)的表单.它将导致表单提交仅处理当前组件(如execute="@this"
).
<h:selectOneMenu value="#{bean.value}" valueChangeListener="#{bean.changeListener}">
<f:selectItems ... />
<f:ajax />
</h:selectOneMenu>
Run Code Online (Sandbox Code Playgroud)
当使用<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>
Run Code Online (Sandbox Code Playgroud)
另一个主要区别是该valueChangeListener
方法在PROCESS_VALIDATIONS
阶段结束时被调用.此时,尚未在模型中更新提交的值.所以你不能通过访问绑定到输入组件的bean属性来获取它value
.你需要得到它ValueChangeEvent#getNewValue()
.顺便提一下,旧的价值也是可用的ValueChangeEvent#getOldValue()
.
public void changeListener(ValueChangeEvent event) {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
// ...
}
Run Code Online (Sandbox Code Playgroud)
<f:ajax listener>
在INVOKE_APPLICATION
阶段期间调用该方法.此时,提交的值已在模型中更新.您可以通过直接访问绑定到输入组件的bean属性来获取它value
.
private Object value; // +getter+setter.
public void ajaxListener(AjaxBehaviorEvent event) {
System.out.println(value); // Look, (new) value is already set.
}
Run Code Online (Sandbox Code Playgroud)
此外,如果您需要根据提交的值更新另一个属性,那么在您使用时它将失败,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());
}
Run Code Online (Sandbox Code Playgroud)
使用<f:ajax listener>
,如果你需要执行的新改变价值的商业行为而已.即你实际上只对新值感兴趣(例如填充第二个下拉列表).
public void ajaxListener(AjaxBehaviorEvent event) {
selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}
Run Code Online (Sandbox Code Playgroud)
如果您在执行业务操作时实际上也对旧值感兴趣,那么请回退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
// ...
}
Run Code Online (Sandbox Code Playgroud)