<f:selectItems> 中的对象作为 itemValue [重复]

Posted

技术标签:

【中文标题】<f:selectItems> 中的对象作为 itemValue [重复]【英文标题】:Object as itemValue in <f:selectItems> [duplicate] 【发布时间】:2011-06-05 20:07:28 【问题描述】:

标签中是否可以将对象作为itemValue

例如我有一个类 Foo:

public class Foo 
  private int id;
  private String name;
  private Date date;

还有一个类吧

public class Bar 
  private Foo foos;


public class BarBean 
  private Set<Foo> foos;

现在在一个名为 BarBean 的 Bean 中,我需要一个从 User 获取当前 Bar 的 Foo ,如下所示:

<h:selectOneMenu value="#barBean.bar.foo" required="true">
 <f:selectItems value="#barBean.foos"  var="foo" itemLabel="#foo.name" itemValue="#foo" />
</h:selectOneMenu>

---------------已编辑:

my converter:

package ir.khorasancustoms.g2g.converters;

import ir.khorasancustoms.g2g.persistance.CatalogValue;
import java.util.ResourceBundle;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.FacesConverter;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;

@FacesConverter("ir.khorasancustoms.CatalogValueConverter")
public class CatalogValueConverter implements Converter 

  @Override
  public Object getAsObject(FacesContext context, UIComponent component, String value) 
    SessionFactory factory = new Configuration().configure().buildSessionFactory();
    Session session = factory.openSession();

    try 
      int id = Integer.parseInt(value);
      CatalogValue catalogValue = (CatalogValue) session.load(CatalogValue .class, id);
      return catalogValue;
     catch (Exception ex) 
      Transaction tx = session.getTransaction();
      if (tx.isActive()) 
        tx.rollback();
      
      ResourceBundle rb = ResourceBundle.getBundle("application");
      String message = rb.getString("databaseConnectionFailed");
      FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_FATAL, message, message));
     finally 
      session.close();
    

    return null;
  

  @Override
  public String getAsString(FacesContext context, UIComponent component, Object value) 
    return ((CatalogValue) value).getId() + "";
  


还有我的小脸:

    <h:outputText value="#lbls.paymentUnit:"/>
    <h:selectOneMenu id="paymentUnit" label="#lbls.paymentUnit" value="#price.price.ctvUnit" required="true">
      <f:selectItems value="#price.paymentUnits"/>
      <f:converter converterId="ir.khorasancustoms.CatalogValueConverter"/>
    </h:selectOneMenu>
    <h:message for="paymentUnit" infoClass="info" errorClass="error" warnClass="warning" fatalClass="fatal"/>

【问题讨论】:

OmniFaces 实现了一个解决方案,使用自定义转换器将复杂对象用作 itemValue。更多信息here 【参考方案1】:

是的这是可能的。

您需要编写一个转换器,将 Foo 转换为SelectItem

Check implementation and very good article here

【讨论】:

你指向的文章是正确的,但你自己的总结并不完全正确。转换器不会转换为SelectItem,而是将模型对象(此处为Foo)转换为字符串表示形式并从字符串表示形式转换回来。对于此 String 表示形式,采用模型对象的键或 ID,并将此 ID 转换回对象,使用 DAO。 我按照教程创建了一个转换器,但是设置bean值失败,我更新了我的问题,请看一下我的代码。【参考方案2】:

Jigar 引用的 BalusC 的文章提供了两个出色的解决方案。它是通过使用 DAO 的转换器或通过在后台 bean 中来回转换的字符串。

另一种解决方案是这两者的混合。通过例如f:param 你可以让转换器访问一个 EL 值表达式,该表达式指向提到的支持 bean BalusC 中的 Map。不是 DAO,每次转换都需要访问数据库,而是参考 Map。

这允许您在&lt;f:selectItems&gt; 标记中使用完整的 Foo 对象,并为您节省每次回发后对数据库的可能调用。然而,成本是编码的一些额外复杂性,因为您必须提供转换器、参数和映射。

(我必须补充一点,当支持 bean 在视图范围或更大范围内时,这样的 Map 效果最好。当它在请求范围内时,它不会真正为您节省 DB 调用)

【讨论】:

我明白了,但在第一次接触转换器时对我来说有点复杂,我只需要在对象和 ID 之间进行转换,我认为我已经完成了,但它最终导致验证错误! :( @Ehsun:什么验证错误? “价值无效”?如果是这样,请检查this answer。 我没有重写equals方法,我解决了问题。谢谢【参考方案3】:

我在 Myfaces 2.0.2 上,这可行

<h:selectOneMenu value="#barBean.bar.foo" required="true">
 <f:selectItems value="#barBean.foos"  var="foo" itemLabel="#foo.name" itemValue="#foo" />
</h:selectOneMenu>

甚至更好

<h:selectOneMenu value="#barBean.bar.foo" required="true">
 <f:selectItems value="#barBean.foos"  />
</h:selectOneMenu>

有效,itemLabel 默认为 foo.toString() - 不知道是否重要,但 foos 是 List&lt;Foo&gt; 而不是 Set

如果使用&lt;f:converter&gt;,则不需要

@FacesConverter(forClass = Foo.class)

在 FooConverter 之前

【讨论】:

以上是关于<f:selectItems> 中的对象作为 itemValue [重复]的主要内容,如果未能解决你的问题,请参考以下文章

JSF-2 f:带有Map的selectItems不显示itemLabel

JSF 2 - f:selectItems 与日期键映射

JSF-2 f:selectItems with Map 不显示 itemLabel

何时使用 valueChangeListener 或 f:ajax 监听器?

如何遍历STL映射(查找所有可能的对)

如何将不同的对添加到集合中?