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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11879138/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-06 10:48:21  来源:igfitidea点击:

When to use valueChangeListener or f:ajax listener?

ajaxjsfjsf-2listenervaluechangelistener

提问by Danijel

What's the difference between the following two pieces of code - with regards to listenerplacement?

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

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

and

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

回答by BalusC

The valueChangeListenerwill only be invoked when the form is submitted andthe submitted value is different from the initial value. It's thus not invoked when onlythe HTML DOM changeevent is fired. If you would like to submit the form during the HTML DOM changeevent, then you'd need to add another <f:ajax/>without a listener(!) to the input component. It will cause a form submit which processes only the current component (as in execute="@this").

valueChangeListener形式被提交时将只被调用提交的值是从初始值不同。因此,当change触发HTML DOM事件时不会调用它。如果您想在 HTML DOMchange事件期间提交表单,那么您需要向<f:ajax/>输入组件添加另一个没有侦听器(!)的表单。它将导致表单提交,该表单仅处理当前组件(如 中所示execute="@this")。

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


When using <f:ajax listener>instead of valueChangeListener, it would by default executed during the HTML DOM changeevent already. Inside UICommandcomponents and input components representing a checkbox or radiobutton, it would be by default executed during the HTML DOM clickevent only.

当使用<f:ajax listener>代替 时valueChangeListener,默认情况下它会在 HTML DOMchange事件期间执行。在UICommand表示复选框或单选按钮的组件和输入组件中,默认情况下它只会在 HTML DOMclick事件期间执行。

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


Another major difference is that the valueChangeListenermethod is invoked during the end of the PROCESS_VALIDATIONSphase. At that moment, the submitted value is not been updated in the model yet. So you cannot get it by just accessing the bean property which is bound to the input component's value. You need to get it by ValueChangeEvent#getNewValue(). The old value is by the way also available by ValueChangeEvent#getOldValue().

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

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


The <f:ajax listener>method is invoked during INVOKE_APPLICATIONphase. At that moment, the submitted value is already been updated in the model. You can just get it by directly accessing the bean property which is bound to the input component's value.

<f:ajax listener>方法在INVOKE_APPLICATION阶段期间被调用。此时,提交的值已经在模型中更新。您可以通过直接访问绑定到输入组件的 .bean 属性的 bean 属性来获取它value

private Object value; // +getter+setter.

public void ajaxListener(AjaxBehaviorEvent event) {
    System.out.println(value); // Look, (new) value is already set.
}


Also, if you would need to update anotherproperty based on the submitted value, then it would fail when you're using valueChangeListeneras the updated property canbe overridden by the submitted value during the subsequent UPDATE_MODEL_VALUESphase. That's exactly why you see in old JSF 1.x applications/tutorials/resources that a valueChangeListeneris in such construct been used in combination with immediate="true"and FacesContext#renderResponse()to prevent that from happening. After all, using the valueChangeListenerto execute business actions has actually always been a hack/workaround.

此外,如果您需要根据提交的值更新另一个属性,那么在您使用时它会失败,valueChangeListener因为更新的属性可以在后续UPDATE_MODEL_VALUES阶段被提交的值覆盖。这正是您在旧的 JSF 1.x 应用程序/教程/资源中看到valueChangeListener这种构造中的 a 被结合使用immediate="true"FacesContext#renderResponse()防止这种情况发生的原因。毕竟,使用valueChangeListener来执行业务操作实际上一直是一种黑客/解决方法。

Summarized: Use the valueChangeListeneronly if you need to intercept on the actual value change itself. I.e. you're actually interested in boththe old and the new value (e.g. to log them).

总结:valueChangeListener仅当您需要拦截实际值更改本身时才使用。即您实际上对旧值和新值感兴趣(例如记录它们)。

public void changeListener(ValueChangeEvent event) {
    changeLogger.log(event.getOldValue(), event.getNewValue());
}

Use the <f:ajax listener>only if you need to execute a business action on the newly changed value. I.e. you're actually interested in onlythe new value (e.g. to populate a second dropdown).

<f:ajax listener>仅当您需要对新更改的值执行业务操作时才使用。即您实际上对新值感兴趣(例如填充第二个下拉列表)。

public void ajaxListener(AjaxBehaviorEvent event) {
    selectItemsOfSecondDropdown = populateItBasedOn(selectedValueOfFirstDropdown);
}

If you're actually also interested in the old value while executing a business action, then fall back to valueChangeListener, but queue it to the INVOKE_APPLICATIONphase.

如果您在执行业务操作时实际上也对旧值感兴趣,则回退到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
    // ...
}

回答by a.u.r

for the first fragment (ajax listener attribute):

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

The "listener" attribute of an ajax tag is a method that is called on the server side every time the ajax function happens on the client side. For instance, you could use this attribute to specify a server side function to call every time the user pressed a key

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

but the second fragment (valueChangeListener) :

但是第二个片段 (valueChangeListener) :

The ValueChangeListener will only be called when the form is submitted, not when the value of the input is changed

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

*you might like to view this handy answer

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