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

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)


a.u*_*u.r 9

对于第一个片段(ajax监听器属性):

ajax标记的"listener"属性是每次在客户端发生ajax函数时在服务器端调用的方法.例如,您可以使用此属性指定每次用户按下某个键时要调用的服务器端函数

但第二个片段(valueChangeListener):

只有在提交表单时才会调用ValueChangeListener,而不会在更改输入值时调用

*您可能希望看到这个方便的答案