2011-10-31 53 views
3

我正在学习如何使用JSF使用事件。出于某种原因,当我更改下拉菜单的值时,程序不会更改文本字段中的值。该页面加载并显示“德国”,但不会将文本字段更改为“DE”。有什么建议么?JSF ValueChangeListener不起作用

的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(); 
} 

} 
+0

该输入字段*是否真的需要是输入字段?它不应该只是只读或输出字段吗? – BalusC

+0

我只是这样做,以了解它是如何工作的。我有另一个更大的程序,我使用它来在选择时自动输入默认值。这是为了测试。我只需要弄清楚如何更改下拉菜单值更改时的文本字段。 – user1011376

回答

13

你基本上滥用valueChangeListener作为actionListener。值更改侦听器可以访问两个旧的和新的值,正好在新的输入值被提交和模型值被更新之间,以便您可以例如添加一个关于价值变化。你显然对旧价值不感兴趣。你根本不感兴趣的价值变化事件。您只对新模型的价值感兴趣。所以你不应该使用值更改监听器。

通常情况下,您希望在动作侦听器方法中完成这项工作。您可以使用<f:ajax>定义一个Ajax动作侦听器:

<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}" /> 

public void changeEvent() { 
    selectedItem = selectedItem; 
} 

但既然你已经绑定的输入属性相同的下拉菜单中,整个听众是多余的。就在下面应该为你做:

<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}" /> 

,你所看到的是,因为onchange="submit()"本质提交整个形式,包括所有其他输入字段的问题。由于JSF按顺序处理输入字段,并且已将这两个字段绑定到相同的属性,所以值<h:inputText>将覆盖值<h:selectOneMenu>。根据我对这个问题的评论,当你将它作为<h:inputText readonly="true"><h:outputText>(这样它就不会将其值提交给服务器)时,你就不会遇到这个问题。

+0

很好的回答!它帮助我 –

1

更改为输出文本组件,看看它是否工作

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

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

商祺!

+0

工作。它如何在输入文本字段上不起作用?该程序供用户选择其数据库引擎(MySQL,SQLServer,Oracle,PostgreSQL)。我需要在文本字段中放置一个默认端口,并允许用户在使用其他端口时编辑该字段。 – user1011376

+0

在这种情况下,您可以尝试将另一个侦听器绑定到inputText组件(如onchange)。我强烈推荐使用f:ajax标签以及上面提到的其他海报。希望这个作品! – Mechkov