Coming Up for Air

A ValueChangeListener Question and Answer

At the lunch session of the OKC JUG today, a question was asked about the difference between the valueChangeListener attribute and <f:valueChangeListener/>. That is,

1
2
3
4
<h:selectOneMenu id="optionMenu" value="#{optionBean.selectedOption}"
        valueChangeListener="#{optionBean.optionChanged}" onchange="submit()">
    <f:selectItems value="#{optionBean.optionList}" />
</h:selectOneMenu>

and

1
2
3
4
<h:selectOneMenu id="optionMenu" value="#{optionBean.selectedOption}" onchange="submit()">
    <f:selectItems value="#{optionBean.optionList}" />
    <f:valueChangeListener type="com.mycompany.MyValueChangeListenerImpl" />
</h:selectOneMenu>

The question was, which is "better?" There was also a question if the latter form automatically handled the JS on the parent component. I will now attempt to answer those questions. :)

The former form takes a MethodExpression (#{optionBean.optionChanged}) that points to a method that satisfies the following method signature:

1
public void valueChangeListener(ValueChangeEvent e);

The latter form points to a class that implements the ValueChangeListener interface:

1
2
3
4
5
public class MyValueChangeListener implements ValueChangeListener  {
    void processValueChange(ValueChangeEvent event) throws AbortProcessingException {
        //...
    }
}

You can also use "binding" with the component:

1
2
<f:valueChangeListener type="com.mycompany.MyValueChangeListenerImpl"
    binding="#{optionBean.valueChangeListener}"/>

In OptionBean, you would have a method like this:

1
2
3
public ValueChangeListener getValueChangeListener() {
    return new MyValueChangeListener();
}

If the binding returns null, and the type is specified, then a ValueChangeListener of the specified type is created and set on the binding (i.e., setValueChangeListener(ValueChangeListener vcl) would be called). If the binding is non-null, though, the type is ignored.

Note that both methods require that the user manually add the JS to the component. I can think of a couple of reasons why this is done, though they may not be the official reasons. While it could be done (maybe), care would have to be taken to determine into which event to hook. Some form elements might take onchange, while others take onblur. In the event of <h:inputText>, for example, does the user want to fire this onchange or onblur? Most likely onblur, but should the framework assume that and cause problems for the user? Probably not. Another reason, which is, to me, more significant, is that JSF doesn’t know when the listener should fire. Should it fire as soon as the field is left? What if there are several VCLs that the user wants to fire at the same time? Or perhaps the VCL is there to change server state when the user submits the form rather than changing UI state. There’s no way to tell for sure, so the onus for controlling the timing of the event falls on the page author, and rightly so, I think.

There’s a lot there, so I help it helps more than confuses. If it DOES confuse, feel free to ask for clarification.

Quotes

Sample quote

Quote source