Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JSF ValueChangeListener not working

I am learning how to use events with JSF. For some reason, the program is not changing the value in the text field when I change the value of the dropdown menu. The page loads and shows "Germany", but does not change the text field to "DE". Any suggestions?

Index.xhtml:

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
  xmlns:f="http://java.sun.com/jsf/core"
  xmlns:h="http://java.sun.com/jsf/html">
<h:head>
    <title>Facelet Title</title>
</h:head>
<h:body>
    <f:view>
        <h:form>
            <h:selectOneMenu value="#{Bean.selectedItem}" valueChangeListener="#{Bean.changeEvent}" onchange="submit()"  >
                <f:selectItems value="#{Bean.itemsList}" />
            </h:selectOneMenu>
            <br />
            <h:inputText value="#{Bean.selectedItem}" />
        </h:form>
    </f:view>
</h:body>

MyBean.java

import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import java.util.ArrayList;
import javax.faces.model.SelectItem;
import javax.faces.event.ValueChangeEvent;
@ManagedBean (name = "Bean")
@RequestScoped
public class MyBean {

private static ArrayList menuItems;
private String selectedItem = "EN";
static {
    menuItems = new ArrayList();
    menuItems.add(new SelectItem("EN", "English"));
    menuItems.add(new SelectItem("DE", "Germany"));
}

public ArrayList getItemsList() {
    return this.menuItems;
}

public void setSelectedItem(String item) {
    this.selectedItem = item;
}

public String getSelectedItem() {
    return selectedItem;
}

public void changeEvent(ValueChangeEvent e) {
    selectedItem = e.getNewValue().toString();
}

}
like image 208
user1011376 Avatar asked Oct 31 '11 16:10

user1011376


2 Answers

You're basically abusing the valueChangeListener as an actionListener. The value change listener is intented to have access to both the old and new value, right in between when the new input value is been submitted and the model value is been updated, so that you can for example add a log entry about the value change. You are apparently not interested in the old value. You're not interested in the value change event at all. You're only interested in the new model value. So you shouldn't be using the value change listener at all.

Normally, you'd like to do this job in an action listener method. You can use <f:ajax> to define an ajax action listener:

<h:selectOneMenu value="#{Bean.selectedItem}">
    <f:selectItems value="#{Bean.itemsList}" />
    <f:ajax execute="@this" listener="#{Bean.changeEvent}" render="input" />
</h:selectOneMenu>
<h:inputText id="input" value="#{Bean.selectedItem}" />

with

public void changeEvent() {
    selectedItem = selectedItem;
}

But since you've bound the input to the same property as the dropdown, the whole listener is superfluous. Just the following should do it for you:

<h:selectOneMenu value="#{Bean.selectedItem}">
    <f:selectItems value="#{Bean.itemsList}" />
    <f:ajax execute="@this" render="input" />
</h:selectOneMenu>
<h:inputText id="input" value="#{Bean.selectedItem}" />

The problem which you're seeing is because the onchange="submit()" essentially submits the whole form, including all other input fields. As JSF processes input fields in sequence and you've bound the both fields to the same property, the value of <h:inputText> will override the value of <h:selectOneMenu>. As per my comment on the question, you would not have this problem when you made it a <h:inputText readonly="true"> or a <h:outputText> (so that it won't submit its value to the server).

like image 188
BalusC Avatar answered Nov 20 '22 04:11

BalusC


Change this to output text component and see if it works

<h:inputText value="#{Bean.selectedItem}" />

to

<h:outputText value="#{Bean.selectedItem}" />

Regards!

like image 22
Mechkov Avatar answered Nov 20 '22 04:11

Mechkov