【问题标题】:JSF getting object from the selectOneMenuJSF 从 selectOneMenu 获取对象
【发布时间】:2026-01-14 19:00:02
【问题描述】:

我又遇到了 JSF 的问题。我仍在学习,非常感谢您的帮助。

<h:form>
    <h:selectOneMenu value="#{productBean.productName}">
        <f:selectItems value="#{productBean.pizza}" var="pizza" itemValue="#{pizza}" itemLabel="#{pizza.name}" />
        <f:ajax listener="#{productBean.valueChanged(pizza)}" render="pizzaResult" />
    </h:selectOneMenu>
    <h:commandButton value ="Dodaj do zamówienia"/>
    <h:outputText id="pizzaResult" value="#{productBean.message}" />
</h:form>

我只想用自定义对象的参数调用方法valueChanged:Product。方法是这样的:

public void valueChanged(Product prod)
{
    if(prod.getIs_available() == 1)
        message = "yes";
    else
        message = "no";
}

我希望它验证产品是否可用。并将其打印在 outputText 标记中。我认为问题出在 HTML 中,因为所需的所有数据都是字符串,我无法以这种方式发送产品。我应该使用转换器吗?它应该是什么样子?我对转换器了解不多,ProductConverter 的工作示例会让我头脑清醒。 提前致谢。

【问题讨论】:

    标签: jsf object converter selectonemenu


    【解决方案1】:

    来自listener属性的文档:

    签名必须匹配 public void processAjaxBehavior(javax.faces.event.AjaxBehaviorEvent event) throws javax.faces.event.AbortProcessingException

    所以你需要像这样改变你的valueChanged 方法:

    public void valueChanged(AjaxBehaviorEvent ev)
    {
        if(this.getIs_available() == 1)
            message = "yes";
        else
            message = "no";
    }
    

    但是,更简洁的方法是使用自定义 Validator

    【讨论】:

    • 但我需要将值传递给方法
    • 当监听器被调用时,你可以直接从 bean 中获取值,因为它已经被更新了
    • 但我的属性“嵌套”在 ArrayList 中,并且正确的产品具有该属性。无论如何,我需要迭代以在列表中找到合适的产品
    【解决方案2】:

    (我还有一个问题。请阅读) 我想我自己可以像这样解决它:(产品是一个带有产品的数组列表。每个产品都有类似 name 的字段或 is_available 从 productBean 的构造函数中的数据库中获取。我遍历列表寻找正确的名称和然后检查它是否可用。如果没有,我设置正确的消息)

        <h:selectOneMenu value="#{productBean.productName}">
            <f:selectItems value="#{productBean.drink}" var="drink" itemValue="#{drink.name}" itemLabel="#{drink.name}" />
            <f:ajax listener="#{productBean.valueChanged(productBean.productName)}" render="drinkResult" />
        </h:selectOneMenu>
    
    public void valueChanged(String name)
    { 
        Iterator<Product> ie = products.iterator();
        while(ie.hasNext()) 
        {
            Product actualProd = ie.next();
            String prodName =actualProd.getName();
            int available =actualProd.getIs_available();
            if(prodName.equals(name) && available == 0)
            {
                System.out.println(prodName + available);
                message = " No rpoduct in store, sorry";
                break;
            }
            else
                message = "";
        }
    }
    

    但我不确定这是做这些事情的正确方法。你认为呢? 我想学习用 Java EE 编写 Web 应用程序,因为它们应该被编写。 “好吧,它有效”——这对我来说还不够。

    【讨论】:

    • 正如你自己所说的 - 你需要一个转换器。有关教程,请参阅 here。您基本上需要在 getAsObject 方法中适应您在此处的逻辑。如果您有重复的产品名称,则会出现唯一的问题 - 如果是这种情况,最好为 itemValue 使用产品 ID。
    • 是的,名称只是临时的,因为我还没有在 bean 中为 id 创建字段
    • 您不需要在此处接受参数的方法,因为您的 productName 已经 productBean 的属性,已由 JSF 设置,并且因此在标准方法中可用。
    【解决方案3】:

    您不需要在侦听器中传递额外的参数,因为转换和验证的值将存在于您的 bean 中。因此,您可以直接在该对象上调用方法。您需要实现Converter 并将&lt;h:selectOneMenu&gt;value 绑定到您的模型类。

    因此,假设您的 pizzaPizza 类型,您的设置将如下所示。

    观点:

    <h:form>
        <h:selectOneMenu value="#{productBean.product}" converter="#{pizzaConverter}">
            <f:selectItems value="#{productBean.pizza}" var="pizza" itemValue="#{pizza}" itemLabel="#{pizza.name}" />
            <f:ajax listener="#{productBean.valueChanged}" render="pizzaResult" />
        </h:selectOneMenu>
        <h:commandButton value ="Dodaj do zamówienia"/>
        <h:outputText id="pizzaResult" value="#{productBean.message}" />
    </h:form>
    

    豆子:

    @ManagedBean
    @ViewScoped
    public class ProductBean implements Serializable {
        private Pizza product;//getter+setter
        private String message;//getter
        public void valueChanged(AjaxBehaviorEvent abe) {
            message = ((product == null) || product.isAvailable()) ? "" : "Product temporarily unavailable";
        }
    }
    

    并且您需要正确实施转换器。我的例子here,还有很多关于 Stack Overflow 上转换器使用的例子。

    【讨论】:

    • "您需要正确实现转换器。"这对我来说是个棘手的部分。
    • 您不需要遵循这种解决方法。它既不好又消耗资源。您应该知道如何实现转换器。
    • 给你举了一个例子。当您了解转换器的全部内容时,这真的很容易:)