开发者

Object as itemValue in <f:selectItems> [duplicate]

开发者 https://www.devze.com 2023-02-03 00:18 出处:网络
This question already has answers here: How to populate options of h:selectOneMenu from database? (5 answers)
This question already has answers here: How to populate options of h:selectOneMenu from database? (5 answers) Closed 5 years ago.

Is it possible to have objects as itemValue in tag?

for example I have a class Foo:

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

And another class Bar

public class Bar {
  private Foo foos;
}

public class BarBean {
  private Set<Foo> foos;
}

Now in a Bean called BarBean I need to have a to get the Foo of the current Bar from User like this:

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

---------------edited:

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));
    } final开发者_开发百科ly {
      session.close();
    }

    return null;
  }

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

}

and my facelet:

    <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"/>


Yes it is possible.

You need to write a converter that will convert Foo to SelectItem

Check implementation and very good article here


BalusC's article as referenced by Jigar gives two excellent solutions. It's via a converter that uses a DAO or via Strings which get converted back and forth in the backing bean.

One additional solution is a hybrid of those two. Via e.g. an f:param you can give the converter access to an EL value expression that points to the Map in the backing bean BalusC mentioned. Instead of the DAO, which might need to access the DB for each conversion, the Map is consulted.

This allows you to use the full Foo object within the <f:selectItems> tag and saves you the possible call to the DB after each post back. The cost is however some extra complexity in coding as you have to provide the converter, the parameter and the map.

(I do have to add btw that such a Map works best when the backing bean is in the view scope or a larger scope. It won't really save you on DB calls when it's in request scope)


I'm on Myfaces 2.0.2 and this works

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

or even better

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

works , with itemLabel defaulted to foo.toString()- Dunno if it matters but foos is a List<Foo> not a Set

The <f:converter> isnt necessary if using

@FacesConverter(forClass = Foo.class)

before the FooConverter

0

精彩评论

暂无评论...
验证码 换一张
取 消