2011-01-08 5 views
5

È possibile avere oggetti come itemValue nel tag?Oggetto come itemValue in <f: selectItems>

per esempio ho una classe Foo:

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

E un'altra classe Bar

public class Bar { 
    private Foo foos; 
} 

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

Ora in una Bean chiamato BarBean ho bisogno di avere un per ottenere il Foo della corrente Bar dalle utente in questo modo:

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

--------------- modificato:

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

} 

e la mia 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 implementa una soluzione per utilizzare oggetti complessi come itemValue utilizzando un convertitore personalizzato .. Ulteriori informazioni [qui] (http: //showcase-omnifaces.rhcloud.it/vetrina/convertitori/SelectItemsConverter.xhtml) –

risposta

4

è possibile.

Hai bisogno di scrivere un convertitore che permette di convertire Foo a SelectItem

Check implementation and very good article here

+3

L'articolo a cui punti è visibile, ma il tuo sommario non è completamente corretto. Il convertitore non converte in un '' SelectItem'', ma converte l'oggetto del modello (Foo qui) dentro e indietro da una rappresentazione String. Per questa rappresentazione di stringa viene presa la chiave o l'ID dell'oggetto modello e per convertire questo ID in un oggetto viene utilizzato un DAO. –

+1

Ho creato un convertitore in base al tutorial ma non riesce ad impostare il valore del bean, ho aggiornato la mia domanda, dare un'occhiata al mio codice per favore. – ehsun7b

2

articolo di BalusC come riferimento da Jigar dà due soluzioni eccellenti. È tramite un convertitore che utilizza un DAO o tramite stringhe che vengono convertiti avanti e indietro nel bean di supporto.

Una soluzione aggiuntiva è un ibrido di questi due. Ad es. a f:param è possibile fornire al convertitore l'accesso a un'espressione di valore EL che punta alla mappa nel bean di supporto BalusC menzionato. Invece del DAO, che potrebbe dover accedere al DB per ogni conversione, viene consultata la mappa.

Ciò consente di utilizzare l'intero oggetto Foo all'interno del tag <f:selectItems> e di salvare l'eventuale chiamata al DB dopo ogni postback. Il costo è comunque una complessità extra nella codifica in quanto è necessario fornire il convertitore, il parametro e la mappa.

(devo aggiungere btw che tale mappa funziona meglio quando il backing bean è nel campo di applicazione visualizzazione o di un ambito più ampio. Non sarà davvero risparmiare sul DB chiama quando è in richiesta di portata)

+0

Vedo, ma è un po 'complesso per me nel primo contatto con Converters, ho solo bisogno di una conversione tra Object e ID che penso di aver fatto, ma finisce con l'errore Validation! :( – ehsun7b

+0

@Ehsun: quale errore di convalida? "Valore non valido"? In tal caso, selezionare [questa risposta] (http://stackoverflow.com/questions/3039338/jsf-validation-error-shown-by-hmessage-while -updating-model-why/3039886 # 3039886). – BalusC

+0

Non ho eseguito l'override del metodo di uguale, ho risolto il problema. Grazie – ehsun7b

1

sono su MyFaces 2.0.2 e questo funziona

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

o meglio ancora

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

opere, con itemLabel default a foo. toString() - so se è importante ma foos è un non List<Foo> un set

Il <f:converter> isnt necessaria se si utilizza

@FacesConverter(forClass = Foo.class) 

prima che i FooConverter

Problemi correlati