7

HI,

Please see the following code:

                <h:selectOneMenu id="countries" value="#{countryBean.selectedCountry}" onchange="submit()
                                    valueChangeListener="#{countryBean.changeCountry}">
                    <f:selectItems value="#{countryBean.countries }" />
                </h:selectOneMenu>  

Backing Bean

public void changeCountry(ValueChangeEvent event){      
    String newValue = (String)event.getNewValue();
    String oldValue = (String)event.getOldValue();

    System.out.println("New Value : " + newValue);
    System.out.println("Old Value : " + oldValue);

    if ("1".equals(newValue)){
        this.countries = new ArrayList<SelectItem>();
        this.cities.add(new SelectItem("1","Delhi"));
        this.cities.add(new SelectItem("2","Mumbai"));
    }
    if ("2".equals(newValue)){
        this.cities = new ArrayList<SelectItem>();
        this.cities.add(new SelectItem("1","Mossco"));
    }       
}

Please let me know if the implementation is correct. It is working fine. My questions are:

  • What is the advantage of adding the f:valueChangeListener tag inside the h:selectOneMenu tag. I have used the normal attribute valueChangeListener="#{countryBean.changeCountry}".
  • Is it necessary to use onchange="submit() this code to change the values.
  • What is difference between writing the custom listeners by implementing the ActionListener interface and just using the attribute in the UIComponent tags (action="methodName"). Please explain me.
Krishna
  • 7,154
  • 16
  • 68
  • 80
  • My opinion is that the separate listener implementation is useful when we are submitting the form, there are multiple components values would have changed. We can do that in the processValueChange method. If we are attaching with the attribute, that will be useful for the single component. Please help me if I am wrong. – Krishna Jan 26 '11 at 05:43

3 Answers3

21

The ValueChangeListener will only be called when the form is submitted, not when the value of the input is changed. Thus, if you want to run this listener when the value is modified, you have two solutions:

  1. Submit your form when the onchange event is fired (this is what you did in your code);
  2. Use an Ajax call instead, by using some dedicated components (already integrated in JSF2, with <f:ajax>, or third-parties libraries such as Richfaces, Primefaces...).

Here is an example with Richfaces:

<h:selectOneMenu id="countries" value="#{countryBean.selectedCountry}" valueChangeListener="#{countryBean.changeCountry}">
    <a4j:support event="onchange" .../>
    <f:selectItems value="#{countryBean.countries }" />
</h:selectOneMenu>

Regarding the code of your listener, it seems correct, but why question is why do you need a ValueChangeListener here? Indeed, this listener is usefull when you want to track a modification of a value. That's why the ValueChangeEvent provides both getOldValue() and getNewValue() methods.

In your code, you do not care about the old value, so basically, you could "simply" do an action instead of a valueChangeListener (ex. with Richfaces):

<h:selectOneMenu id="countries" value="#{countryBean.selectedCountry}">
    <a4j:support event="onchange" actionListener="#{countryBean.changeCountry}"/>
    <f:selectItems value="#{countryBean.countries }" />
</h:selectOneMenu>

Finally, regarding the difference between the valueChangeListener attribute and <f:valueChangeListener> is that the first binds a Java method (#{myBean.myMethod}), while the second binds a Java class (type="com.foo.MyListenerClass") which implements the ValueChangeListener interface. So the second one could be more generic than the first one...

Romain Linsolas
  • 79,475
  • 49
  • 202
  • 273
7

Romaintaz already pointed out the most, I just wanted to get straight on your concrete questions:

What is the advantage of adding the f:valueChangeListener tag inside the h:selectOneMenu tag. I have used the normal attribute valueChangeListener="#{countryBean.changeCountry}".

As Romaintaz said, the attribute points to a method and the f: tag points to a class. Another advantage is that you can have multiple of them, whenever that is necessary.

Is it necessary to use onchange="submit() this code to change the values.

That Javascript doesn't change the values. That Javascript submits the entire form without the need to pressing the submit button yourself, whenever the value has been changed by the enduser. No, that is not necessary. You can also just remove it and expect that the enduser presses the submit button himself. Once again, that JavaScript is not part of JSF.

What is difference between writing the custom listeners by implementing the ActionListener interface and just using the attribute in the UIComponent tags (action="methodName").

This question is already asked before: difference between action and actionlistener.

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
0

The solution from romaintaz of calling an action instead of valueChangeListener is also great because in the case of "change" event the action is called after the model is updated (allowing for a DB update for example) while the valueChangeListener is called before....

Manu de Hanoi
  • 272
  • 3
  • 14