2011-01-08 13 views
5

Czy w tagu można umieścić obiekty jako itemValue?Obiekt jako elementwartość w <f: selectItems>

na przykład mam klasy Foo:

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

a inna klasa Bar

public class Bar { 
    private Foo foos; 
} 

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

Teraz w Bean nazwie BarBean muszę mieć, aby uzyskać Foo bieżącego barze od użytkownik nie tak:

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

--------------- edycja:

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() + ""; 
    } 

} 

i mój 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"/> 
+0

OmniFaces realizuje rozwiązanie zastosowania skomplikowanych obiektów jak ItemValue stosując niestandardowy Konwerter .. Więcej informacji [tutaj] (http: //showcase-omnifaces.rhcloud.com/showcase/converters/SelectItemsConverter.xhtml) –

Odpowiedz

4

Tak jest to możliwe.

Trzeba napisać konwerter, który będzie konwertować Foo do SelectItem

Check implementation and very good article here

+3

Artykuł, o którym mówisz, jest na miejscu, ale twoje własne podsumowanie nie jest całkowicie poprawne. Konwerter nie przekształca się w '' SelectItem'', ale konwertuje obiekt modelu (tutaj Foo) na i z powrotem z reprezentacji String. W przypadku tej reprezentacji String pobierany jest klucz lub identyfikator obiektu modelu, a w celu przekształcenia tego identyfikatora z powrotem w obiekt używany jest obiekt DAO. –

+1

Stworzyłem konwerter zgodnie z samouczkiem, ale nie udało mu się ustawić wartości fasoli, zaktualizowałem moje pytanie, proszę spojrzeć na mój kod, proszę. – ehsun7b

2

artykule BalusC jako odwołuje Jigar daje dwie doskonałe rozwiązania. Jest to przez konwerter, który używa DAO lub przez Struny, które są konwertowane tam i z powrotem w zapleczu.

Jednym z dodatkowych rozwiązań jest ich hybryda. Przez np. f:param możesz dać konwerterowi dostęp do wyrażenia wartości EL, które wskazuje na Mapę w BalusC podkładu wsparcia wspomnianego. Zamiast DAO, które może potrzebować uzyskać dostęp do bazy danych dla każdej konwersji, konsultowana jest Mapa.

Umożliwia to użycie pełnego obiektu Foo w tagu <f:selectItems> i zapisuje możliwe połączenie z DB po każdym powrocie z powrotem. Koszt jest jednak trochę skomplikowany w kodowaniu, ponieważ trzeba podać konwerter, parametr i mapę.

(muszę dodać przy okazji, że taka mapa działa najlepiej, gdy fasola podkład jest w zakresie widoku lub większym zakresie. To nie będzie naprawdę zaoszczędzić na rozmowach DB kiedy to we wniosku zakres)

+0

Widzę, ale jest to trochę skomplikowane dla mnie w pierwszym kontakcie z Konwerterem, potrzebuję tylko konwersji między Obiektem a ID, co, jak sądzę, zrobiłem, ale kończy się błędem Walidacji! :( – ehsun7b

+0

@Ehsun: Jaki błąd sprawdzania poprawności? "Niepoprawna wartość"? Jeśli tak, sprawdź [tę odpowiedź] (http://stackoverflow.com/questions/3039338/jsf-validation-error-shown-by-hmessage-while -updating-model-why/3039886 # 3039886). – BalusC

+0

Nie zastąpiłem metody równości, rozwiązałem prob. – ehsun7b

1

jestem na MyFaces 2.0.2 i działa to

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

lub nawet lepiej

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

działa, z itemLabel domyślnie foo. toString() - Dunno jeśli liczy ale Foos jest nie List<Foo> się zestaw

<f:converter> existing konieczny, jeśli przy użyciu

@FacesConverter(forClass = Foo.class) 

przed FooConverter

Powiązane problemy