将selectOneMenu复杂对象作为选中的项目进行检索。

问题描述 投票:1回答:2

我开始使用JSF(Mojarra 2.2和Glassfish 4),目前正在练习一个Web应用程序,它的工作是将客户和他们的订单存储在DB中。

当创建一个新的订单时,有一个功能是允许从JSF的客户机中选择一个现有的客户机。<h:selectOneMenu>. 一个订单实体在其他属性中存储了一个客户实体......

我按照BalusC的伟大回答,预先填充一个 <h:selectOneMenu> 从数据库 (此处),并成功地从存储在急切的ApplicationScoped ManagedBean中的数据中填充了我的数据,但我无法在支持Bean中以复杂对象的形式检索所选项目。它总是空的。

这快把我逼疯了,真的很感谢您的帮助!以下是相关代码片段。

@ManagedBean(eager = true)
@ApplicationScoped
public class Data implements Serializable {

    private static final long serialVersionUID = 1L;

    @EJB
    private ClientDao clientDao;

    private List<Client> clients;

    @PostConstruct
    private void init() {
        clients = clientDao.lister();
    }

    public List<Client> getClients() {
        return clients;
    }

}

订单创建bean(注意:'commande'是指订单;)

@ManagedBean
@RequestScoped
public class CreerCommandeBean implements Serializable {
    private static final long serialVersionUID = 1L;
    private Commande commande;

    private String choixNouveauClient = "nouveauClient";

    @EJB
    private CommandeDao commandeDao;

    public CreerCommandeBean() {
        commande = new Commande();
    }

    public void inscrire() {

        System.out.println("client : " + commande.getClient()); // prints **NULL**
            // ... orderService to store in DB
    }
... getters and setters

客户端转换器。

@FacesConverter(value = "clientConverter", forClass = Client.class)
public class ClientConverter implements Converter {

    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value) {
        if (value == null) {
            return null;
        }

        Data data = context.getApplication().evaluateExpressionGet(context, "#{data}", Data.class);
        for (Client c : data.getClients()) {
            if (c.getId().toString().equals(value)) {
                return c;
            }
        }
        throw new ConverterException(new FacesMessage(String.format("Cannot convert %s to Client", value)));
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value) {
        return (value instanceof Client) ? String.valueOf(((Client) value).getId()) : null;
    }
}

Facelet摘录。

<p:outputPanel id="gridContainerAncienClient">
            <p:selectOneMenu value="#{creerCommandeBean.commande.client}"
                rendered="#{creerCommandeBean.choixNouveauClient == 'ancienClient'}">
                <f:converter converterId="clientConverter" />
                <f:selectItems value="#{data.clients}" var="cli"
                    itemValue="#{cli}" itemLabel="#{cli.prenom} #{cli.nom}" />
            </p:selectOneMenu>
        </p:outputPanel>
jsf facelets selectonemenu
2个回答
1
投票

CreerCommandeBean@RequestScoped. 这意味着它将只为一个请求而存在。当您选择一个客户机被分配到 #{creerCommandeBean.commande.client} 你通过请求来实现。#{creerCommandeBean.commande.client} 现在是选定的客户端。然后请求结束,Bean被销毁,你的 "更改 "也就丢失了。当你试图检索这些数据时,你会再次通过请求来完成。一个新的实例 CreerCommandeBean 被创建,并且构造函数将属性分配给了 commande 与新的 Commande 其所属 client 又可能是 null.

解决办法。 使用更广泛的范围,例如 @ViewScoped 这使得Bean "活 "了下来,只要你呆在同一个视图中--无论你做多少次请求。

提示:使用更广泛的范围。阅读 BalusC的帖子 Communication is JSF 2.0. 在JSF 2.2中,部分内容可能略有不同,但仍然是一个不错的全面介绍。


0
投票

我也被类似的问题卡住了,后来才发现我的Object.Client类中忘记了实现equals()和hashCode()方法。在这种情况下,我的Object.Client类中忘了实现equals()和hashCode()方法。

要怪就怪我自己跳过了在 BalusC的博客.

"...请注意: Object#equals() 实现。这对于JSF来说是非常重要的。 转换后,它会将所选项目与列表中的项目进行比较。由于 Object#equals() 还需要 Object#hashCode(),这也是实施......"

© www.soinside.com 2019 - 2024. All rights reserved.