2015-09-23 4 views
5

Ich versuche, eine Primefaces 5.2 selectOneMenu zu erhalten, Bilder zusammen mit ihren Dateinamen anzuzeigen. Dies ist, was zur Zeit mein xhtml wie folgt aussieht:p: selectOneMenu nicht benutzerdefinierten Inhalt über p: Spalte auf Liste <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> 

Die ManagedBean (imageBean) jedoch

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

und

private String selectedImage; 

public String getSelectedImage() { 
    return selectedImage; 
} 

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

hat, werden die Bilder nicht auf die gerenderte Webseite, nur die Dateinamen (ich würde einen Screenshot posten, aber ich habe nicht genug Reputation). Ich bekomme keine zwei Spalten (zuerst das Bild, dann den Dateinamen), ich bekomme nur den Dateinamen selbst.

Wenn ich den Dateinamen Strings in ein POJO wickeln und einen Konverter verwenden, funktioniert es - aber nur mit Strings tut es nicht.

Wie kann ich dies mit nur Strings arbeiten?

+0

Keine 404s im Protokoll - auch die gleichen URLs funktionieren, wenn ich eine Wrapper-Klasse um die Dateinamen-Strings . Wenn ich einen Hinweis in den Logbüchern gefunden hätte, die ich interpretieren konnte, hätte ich nichts gepostet. – Ginkobonsai

+0

Entschuldigung, ich will damit nicht sagen, dass es keine Hinweise in den Logs gibt, nur dass ich keine erkennen kann. Kannst du mir einen Hinweis geben, wonach ich suche (außer 404, für die ich überprüft habe)? Was mich auch verwirrt, ist, dass das Ändern von Dingen auf der Serverseite (Hinzufügen der Wrapper-Klasse) es funktioniert. – Ginkobonsai

+0

Nein, das gewünschte Element endet nicht in der HTML-Ausgabe - es wird weggelassen. Stattdessen erhalte ich nur den Text (Dateiname).Wenn ich die Wrapper-Klasse verwende, bekomme ich das -Tag ohne Probleme. – Ginkobonsai

Antwort

7

Dieses peinliche Verhalten wird durch SelectOneMenuRenderer source code bestätigt (Zeilennummern entsprechen 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   } 

Also, wenn der Elementwert eine Instanz von String ist, kundenspezifische Inhalte über <p:column> wird völlig ignoriert. Das macht in der Tat keinen Sinn. Die intuitive Erwartung ist, dass der benutzerdefinierte Inhalt durch das Vorhandensein von var Attribut und/oder <p:column> Kindern umgeschaltet wird. Am besten solltest du PrimeFaces Jungs ein Problem melden, um dies zu erklären/verbessern.

Die Arbeit um, abgesehen von nicht-String -typed Elementwerte, verfügt die SelectOneMenuRenderer mit einem benutzerdefinierten Renderer außer Kraft zu setzen, die die String in einem anderen Objekt umschließt, die genau den gleichen Wert in seinem toString() wie StringBuilder zurückzukehren geschehen . Auf diese Weise wird der Renderer täuschen, dass die Werte keine Instanz von String sind. Froh, dass sie nicht nach instanceof CharSequence überprüft haben.

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); 
    } 

} 

Um es zu laufen zu erhalten, registrieren Sie es wie unten 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 ... Danke eine Tonne! Ich hätte nie gedacht, dass dieses Verhalten absichtlich ist ... Und doppelt danke für die schöne Workaround! Es gibt einen kleinen Fehler mit der Problemumgehung, wenn Sie (Nicht-String) POJOs verwenden, wenn Sie ein "Nicht-Element" wie die '' in Mein Beispiel - Sie erhalten eine PropertyNotFoundException, weil die POJO-Eigenschaften nicht im StringBuilder-Objekt gefunden werden können. Mein (fauler) Fix ist im Renderer zu verwenden 'if (Wert instanceof String &&!" ". Equals ((String) Wert)) {' – Ginkobonsai

+0

Gern geschehen. Was den Glitch betrifft, hättest du 'itemValue =" # {null} "' verwenden sollen. Siehe auch http://stackoverflow.com/questions/11360030/best-way-to-add-a-nothing-selected-option-to-a-selectonemenu-in-jsf – BalusC

+0

Ah, danke - ich werde das benutzen. BTW: Ich habe im Primefaces-Forum gepostet und zu diesem Thema gefragt, mal sehen, was sie sagen. – Ginkobonsai

0

Der Grund ist, dass die Primefaces-Bibliothek eine Bean im var-Attribut der Komponente selectOneMenu erfasst, aber Sie geben String-Objekte an, die keine Beans sind. Daher gibt die Bibliothek überhaupt keine Spaltenüberlagerung aus. Sie benötigen eine Bean (Wrapper) im Attribut var und den entsprechenden Konverter im Attribut converter.

+0

Ja, das ist die Problemumgehung, die für mich funktioniert - ich hatte nur gehofft, dass es einen einfacheren Weg gab ... – Ginkobonsai

+0

Das ist die Frage, es gibt keine Problemumgehung, weil es keine Lösung gibt. Auf diese Weise können Sie Bilder in ein Primefaces selectOneMenu einfügen. Wenn meine Antwort Ihre Frage klarstellt, akzeptieren Sie bitte meine Antwort. Um eine Antwort als akzeptiert zu markieren, klicken Sie auf das Häkchen neben der Antwort, um sie von leer auf grün umzuschalten. Vielen Dank. – lametaweb

+0

Also ein String ist kein POJO? – Kukeltje

Verwandte Themen