2015-09-23 34 views
5

Sto cercando di ottenere un Primefaces 5.2 selectOneMenu per visualizzare le immagini insieme ai relativi nomi di file. Questo è ciò che il mio XHTML attualmente si presenta come:p: selectOneMenu non esegue il rendering di contenuto personalizzato tramite p: column su List <String>

<h:form> 
<h:panelGrid id="createPanelGrid" columns="2"> 
    <p:outputLabel value="Service Logo:" /> 
    <p:selectOneMenu value="#{imageBean.selectedImage}" var="l"> 
     <f:selectItem itemLabel="Select a logo" itemValue="" /> 
     <f:selectItems value="#{imageBean.imageList}" var="logo" itemLabel="#{logo}" itemValue="#{logo}" /> 
     <p:column> 
      <p:graphicImage value="#{imageBean.imageFolder}/#{l}" style="max-width:50px;max-height:50px;" /> 
     </p:column> 
     <p:column>#{l}</p:column> 
    </p:selectOneMenu> 
</h:panelGrid> 

Il ManagedBean (imageBean) ha

public List<String> getImageList() { 
    List<String> imageList = new ArrayList<String>(); 
    File[] files = absoluteImageFolder.listFiles(); 
    for (File file : files) { 
     imageList.add(file.getName()); 
    }   
    return imageList; 
} 

e

private String selectedImage; 

public String getSelectedImage() { 
    return selectedImage; 
} 

public void setSelectedImage(String selectedImage) { 
    this.selectedImage = selectedImage; 
} 

Tuttavia, le immagini non sono resi sulla pagina web, solo i nomi dei file (vorrei pubblicare uno screenshot ma non ho abbastanza reputazione). Non ottengo due colonne (prima l'immagine, poi il nome del file), ho solo il nome del file stesso.

Quando avvolgo il nome del file String in un POJO e utilizzo un convertitore, funziona, ma solo con Stringhe non funziona.

Come posso farlo funzionare con solo stringhe?

+0

Non ci sono 404s nel registro - anche gli stessi URL funzionano quando uso una classe wrapper attorno alle stringhe filename . Se avessi trovato un indizio nei log che potevo interpretare, non avrei postato. – Ginkobonsai

+0

Scusa, non intendo dire che non ci siano indizi nei registri, solo che non riesco a individuarne alcuno. Puoi darmi un suggerimento su cosa sto cercando (oltre gli 404, per i quali ho controllato)? Inoltre, ciò che mi confonde è che cambiare le cose sul lato server (aggiungendo la classe wrapper) lo fa funzionare. – Ginkobonsai

+0

No, l'elemento desiderato non si trova nell'output HTML, ma viene omesso. Invece, ottengo solo il testo (nome file).Se uso la classe wrapper, ottengo il tag senza problemi. – Ginkobonsai

risposta

7

Questo comportamento imbarazzante è confermato dalla SelectOneMenuRenderer source code (numeri di riga corrispondono 5.2):

260   if(itemValue instanceof String) { 
261    writer.startElement("td", null); 
262    writer.writeAttribute("colspan", columns.size(), null); 
263    writer.writeText(selectItem.getLabel(), null); 
264    writer.endElement("td"); 
265   } 
266   else { 
267    for(Column column : columns) { 
268     writer.startElement("td", null); 
269     renderChildren(context, column); 
270     writer.endElement("td"); 
271    } 
272   } 

Quindi, se il valore oggetto è un'istanza di String, contenuti personalizzati tramite <p:column> viene totalmente ignorato. Questo non ha alcun senso. L'aspettativa intuitiva è che il contenuto personalizzato sia attivato dalla presenza dell'attributo var e/o da <p:column> bambini. È meglio segnalare un problema ai ragazzi di PrimeFaces per spiegare/migliorare questo aspetto.

Il lavoro attorno, oltre a fornire non String valori degli elementi -typed, è quello di sostituire il SelectOneMenuRenderer con un renderer personalizzato che avvolge il String in un altro oggetto che risulta restituire esattamente lo stesso valore nella sua toString(), come StringBuilder . In questo modo il riproduttore verrà ingannato dal fatto che i valori non sono un'istanza di String. Sono contento che non hanno controllato per instanceof CharSequence.

public class YourSelectOneMenuRenderer extends SelectOneMenuRenderer { 

    @Override 
    protected void encodeOptionsAsTable(FacesContext context, SelectOneMenu menu, List<SelectItem> selectItems) throws IOException { 
     List<SelectItem> wrappedSelectItems = new ArrayList<>(); 

     for (SelectItem selectItem : selectItems) { 
      Object value = selectItem.getValue(); 

      if (value instanceof String) { 
       value = new StringBuilder((String) value); 
      } 

      wrappedSelectItems.add(new SelectItem(value, selectItem.getLabel())); 
     } 

     super.encodeOptionsAsTable(context, menu, wrappedSelectItems); 
    } 

} 

Al fine di farlo funzionare, registrarlo come di seguito in faces-config.xml:

<render-kit> 
    <renderer> 
     <component-family>org.primefaces.component</component-family> 
     <renderer-type>org.primefaces.component.SelectOneMenuRenderer</renderer-type> 
     <renderer-class>com.example.YourSelectOneMenuRenderer</renderer-class> 
    </renderer> 
</render-kit> 
+0

Wow ... Grazie mille! Non avrei mai pensato che questo comportamento fosse intenzionale ... E doppio grazie per aver fornito una soluzione gradevole! C'è un piccolo problema con la soluzione alternativa quando si utilizzano POJO (non String) se si dispone di un "non articolo" come '' in il mio esempio: ottieni una proprietà PropertyNotFoundException perché le proprietà del POJO non possono essere trovate sull'oggetto StringBuilder. La mia correzione (lazy) è da utilizzare nel renderer 'if (value instanceof String &&!" ". Equals ((String) value)) {' – Ginkobonsai

+0

Prego. Per quanto riguarda il glitch, dovresti aver usato 'itemValue =" # {null} "'. Vedi anche http://stackoverflow.com/questions/11360030/best-way-to-add-a-nothing-selected-option-to-a-selectonemenu-in-jsf – BalusC

+0

Ah, grazie - Lo userò. BTW: Ho postato nel forum Primefaces e ho chiesto informazioni su questo problema, vediamo cosa dicono. – Ginkobonsai

0

La ragione è che la libreria Primefaces sta esaminando un bean nell'attributo var del componente selectOneMenu, ma si stanno assegnando oggetti String che non sono bean. Quindi la libreria non esegue alcuna sovrapposizione di colonne. È necessario un bean (wrapper) nell'attributo var e il convertitore corrispondente nell'attributo converter.

+0

Sì, questa è la soluzione che funziona per me: avevo solo sperato che esistesse un modo più semplice ... – Ginkobonsai

+0

Questa è la domanda, non c'è soluzione alternativa perché non c'è nulla da aggirare. Questo è il modo per mettere le immagini in Primefaces selectOneMenu. Se la mia risposta chiarisce la tua domanda, per favore accetta la mia risposta. Per contrassegnare una risposta come accettata, fare clic sul segno di spunta accanto alla risposta per passare da vuoto a verde. Grazie. – lametaweb

+0

Quindi una stringa non è un POJO? – Kukeltje