Frage p: selectOneMenu rendert keinen benutzerdefinierten Inhalt über p: column in List


Ich versuche, ein Primefaces 5.2 selectOneMenu zu erhalten, um Bilder zusammen mit ihren Dateinamen anzuzeigen. So sieht meine xhtml momentan aus:

<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) hat

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

Allerdings werden die Bilder nicht auf der Webseite gerendert, 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 umwandele und einen Konverter verwende, funktioniert es - aber nur mit Strings tut es nicht.

Wie kann ich das mit nur Strings arbeiten?


5
2017-09-23 09:27


Ursprung


Antworten:


Dieses peinliche Verhalten wird bestätigt durch SelectOneMenuRenderer Quellcode (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            }

Wenn also der Elementwert eine Instanz von ist String, benutzerdefinierte Inhalte über <p:column> wird total ignoriert. Das macht in der Tat keinen Sinn. Die intuitive Erwartung ist, dass der benutzerdefinierte Inhalt durch die Anwesenheit von aktiviert wird var Attribut und / oder <p:column> Kinder. Am besten solltest du PrimeFaces Jungs ein Problem melden, um dies zu erklären / verbessern.

Die Arbeit, abgesehen von der BereitstellungString-typed item values, ist das Überschreiben der SelectOneMenuRenderer mit einem benutzerdefinierten Renderer, der die String in einem anderen Objekt, das zufällig denselben Wert in seiner zurückgegeben wird toString(), sowie StringBuilder. Auf diese Weise wird der Renderer täuschen, dass die Werte keine Instanz von sind String. Froh, dass sie nicht nachsehen konnten 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);
    }

}

Um es zum Laufen zu bringen, 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>

8
2017-09-23 13:06



Der Grund dafür ist, dass die Primefaces-Bibliothek eine Bean in der var Attribut des selectOneMenu Komponente, 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) in der var Attribut und der entsprechende Konverter in der converter Attribut.


0
2017-09-23 11:50