对象为<f:selectitems> </f:selectitems>中的itemValue

时间:2011-01-08 18:00:40

标签: java jsf java-ee jsf-2

是否可以在标记中将对象设为 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中,我需要有一个从用户那里得到当前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"/>

3 个答案:

答案 0 :(得分:5)

有可能。

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

的转换器

Check implementation and very good article here

答案 1 :(得分:2)

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

另外一个解决方案是这两者的混合。通过例如f:param你可以让转换器访问EL值表达式,该表达式指向支持bean BalusC中提到的Map。

可以参考地图,而不是可能需要为每次转换访问数据库的DAO

这允许您在<f:selectItems>标记内使用完整的Foo对象,并在每次回发后保存对DB的可能调用。然而,由于您必须提供转换器,参数和地图,因此成本会有一些额外的复杂性。

(我必须添加btw,当支持bean在视图范围或更大的范围内时,这样的Map最有效。当它在请求范围内时,它不会真正保存在DB调用上)< / em>的

答案 2 :(得分:1)

我在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() - Dunno如果重要但foos是List<Foo>而不是Set

如果使用

,则<f:converter>不是必需的
@FacesConverter(forClass = Foo.class)
在FooConverter之前