JSF中的ValueChangeListener疑问

7

你好,

请查看以下代码:

                <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"));
    }       
}

请告诉我实现是否正确。它很好地工作了。 我的问题是:
  • h:selectOneMenu标签中添加f:valueChangeListener标签的优点是什么?我已经使用了普通属性valueChangeListener="#{countryBean.changeCountry}"。
  • 必须使用onchange="submit()这段代码来更改值吗?
  • 通过实现ActionListener接口编写自定义侦听器和仅使用UIComponent标记中的属性(action="methodName")之间的区别是什么? 请解释给我听。

我的观点是,当我们提交表单时,独立的监听器实现非常有用,因为可能会有多个组件的值发生变化。我们可以在processValueChange方法中完成这个操作。如果我们将其附加到属性上,那么对于单个组件来说会很有用。如果我有错误,请帮助我纠正。 - Krishna
3个回答

21

ValueChangeListener 只有在表单提交时才会被调用,而不是在输入值被修改时调用。因此,如果您想在值被修改时运行此监听器,您有两个解决方案:

  1. 在触发 onchange 事件时提交您的表单(这就是您在代码中所做的);
  2. 使用 Ajax 调用,通过使用一些专用组件(已经集成在 JSF2 中,例如 <f:ajax>,或第三方库如 Richfaces、Primefaces 等)。

这里是一个使用 Richfaces 的示例:

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

关于您的监听器代码,它似乎是正确的,但问题是为什么你需要在这里使用ValueChangeListener?确实,当您想要跟踪值的修改时,此侦听器非常有用。这就是为什么ValueChangeEvent提供了getOldValue()getNewValue()方法。

在您的代码中,您并不关心旧值,因此基本上,您可以“简单地”执行操作而不是使用valueChangeListener(例如使用Richfaces):

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

最后,关于valueChangeListener属性和<f:valueChangeListener>之间的区别在于,前者绑定一个Java方法(#{myBean.myMethod}),而后者绑定实现了ValueChangeListener接口的Java类(type="com.foo.MyListenerClass")。因此,后者比前者更加通用...


7
Romaintaz已经指出了大部分内容,我只想直接回答您的具体问题:

在h:selectOneMenu标签中添加f:valueChangeListener标签的优点是什么?我已经使用了普通的valueChangeListener="#{countryBean.changeCountry}"属性。

正如Romaintaz所说,该属性指向一个方法,而标签则指向一个类。另一个优点是,您可以拥有多个这样的标签,只要有必要。

使用onchange="submit()"代码更改值是否必要?

那段JavaScript并不会更改值。当终端用户更改值时,该JavaScript将提交整个表单,无需自己按下提交按钮。不,这不是必需的。您也可以将其删除,并期望最终用户自己按下提交按钮。再次强调,该JavaScript不是JSF的一部分。

通过实现ActionListener接口编写自定义侦听器和仅使用UIComponent标记中的属性(action =“methodName”)之间的区别是什么?

两者之间的区别在于,通过实现ActionListener接口编写自定义侦听器可以使您在处理事件时有更多的控制权和灵活性。而仅使用UIComponent标记中的属性则更简单方便。

这个问题已经在此之前被问过了:动作和动作监听器的区别


0

romaintaz 的解决方案调用操作而非 valueChangeListener 也很好,因为在 "change" 事件的情况下,在模型更新后调用了该操作(例如允许进行数据库更新),而 valueChangeListener 则是在之前被调用…


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接