P: dataExporter не распознает p: cellEditor

У меня есть редактируемый <p:dataTable> с <p:cellEditor>, и я хочу экспортировать содержимое этой таблицы в формат PDF с помощью <p:dataExporter>.

Я включил itext 2.1.7 jar. Я получил вывод в формате PDF, но он показывает значения Object#toString() для всех компонентов <p:cellEditor>, например:

[email protected]

Как экспортировать выходные значения <p:cellEditor> вместо?

Ответ 1

<p:cellEditor> действительно не распознается стандартными экспортерами данных PrimeFaces. Ранее я сообщал об этом ребятам из PF issue 4013 с примером, который не только упоминает CellEditor, но также и HtmlGraphicImage (мы используем изображения для показа boolean states, чей alt мы хотели бы показать в отчетах PDF/XML/XLS/CSV).

Сначала создайте новый класс, который расширяет стандарт PDFExporter следующим образом:

public class ExtendedPDFExporter extends PDFExporter {

    @Override
    protected String exportValue(FacesContext context, UIComponent component) {
        if (component instanceof CellEditor) {
            return exportValue(context, ((CellEditor) component).getFacet("output"));
        }
        else if (component instanceof HtmlGraphicImage) {
            return (String) component.getAttributes().get("alt");
        }
        else {
            return super.exportValue(context, component);
        }
    }

}

Затем, чтобы использовать его, вызовите его программно, а не через <p:dataExporter>.

<p:dataTable binding="#{table}" editable="true" ...>
    <p:column><p:cellEditor>...</p:cellEditor></p:column>
    <p:column><p:cellEditor>...</p:cellEditor></p:column>
    <p:column><p:cellEditor>...</p:cellEditor></p:column>
    <p:column exportable="false"><p:rowEditor /></p:column>
</p:dataTable>
<h:commandLink value="PDF" action="#{bean.exportPDF(table, 'filename')}" />

С

public void exportPDF(DataTable table, String filename) throws IOException {
    FacesContext context = FacesContext.getCurrentInstance();
    Exporter exporter = new ExtendedPDFExporter();
    exporter.export(context, table, filename, false, false, "UTF-8", null, null);
    context.responseComplete();
}

Невозможно найти таблицу данных вместо UIComponent#findComponent() и установить только имя файла в действии. Вышеприведенный код является просто образцом.

Ответ 2

Я согласен, я также нахожу этот подход, чтобы настроить поведение Exporter наиболее гибким и наименее болезненным.

Кто-нибудь заинтересован в использовании методов preProcessor/postProcessor с этим? Вот пример, как это сделать.

Я посмел слегка изменить метод из вышеприведенного ответа:

public void exportPDF(DataTable table, String filename, 
        String preProcessor, String postProcessor) throws IOException {

    FacesContext context = FacesContext.getCurrentInstance();
    ExpressionFactory factory = context.getApplication().getExpressionFactory();

    MethodExpression preProcessorME = factory.createMethodExpression(
        context.getELContext(), preProcessor, null, new Class[] {Object.class});
    MethodExpression postProcessorME = factory.createMethodExpression(
        context.getELContext(), postProcessor, null, new Class[] {Object.class});

    Exporter exporter = new ExtendedPDFExporter();
    exporter.export(context, table, filename, false, false, "UTF-8", 
        preProcessorMe, postProcessorME);

    context.responseComplete();

}

И вот как вы используете его на своей странице (опять же, я только что изменил приведенный выше пример):

<p:dataTable binding="#{table}" editable="true" ...>
    <p:column><p:cellEditor>...</p:cellEditor></p:column>
    <p:column><p:cellEditor>...</p:cellEditor></p:column>
    <p:column><p:cellEditor>...</p:cellEditor></p:column>
    <p:column exportable="false"><p:rowEditor /></p:column>
</p:dataTable>
<h:commandLink value="PDF" action="#{bean.exportPDF(table, 'filename', 
    '#{yourBean.preProcessPDF}', '#{yourBean.postProcessPDF}')}" />

Обратите внимание, что там НЕ ЗАЯВЛЕННЫЕ ЗАЯВЛЕНИЯ EL (это не разрешено в любом случае), последние два аргумента - простые строки, содержащие выражения EL.