在不使用 Ajax 的情况下使用 PrimeFaces 提交表单时出错

问题描述 投票:0回答:1

我正在使用 Jakarta Server Faces 和 PrimeFaces 12 开发一个 JavaWeb 项目。我正在尝试处理一个具有 4 个互相更新的 SelectOneMenu 的表单(第一个选定的元素更新第二个中可用的元素,第二个选定的元素第二个更新第三个,依此类推)。我使用了 Ajax,因此更改任何一个 selectOneMenu 的状态都会更新其余 selectOneMenu 的值。

表单的提交按钮处理整个表单,但我需要它而不是使用 Ajax 处理表单,因为此按钮还会下载根据 selectOneMenu 中所选值生成的报告。

如果我将代码 ajax = true 放入表单的提交按钮,它会处理但不会下载文件,但是,如果我禁用按钮的 Ajax,即使在所有 selectOneMenu 中选择了有效值,它们也会抛出错误表明值无效并且表单未完成。

我展示我正在使用的代码:

            #{reportsBean.update_Area()}
            <h:form id="form1">
                <p:growl id="messages" allowDismiss="true"/>
                <div class="row">
                    <div class="col col-sm-6">
                        <p:outputLabel for="areaInput"
                                       styleClass="block"> &Aacute;rea </p:outputLabel> <br/>
                        <p:selectOneMenu value="#{reportsBean.area}"
                                         id="areaInput"
                                         requiredMessage="&Aacute;rea: Es necesario seleccionar una Facultad"
                                         required="true" label="&Aacute;rea">
                            <f:selectItem itemLabel="(Seleccione un &Aacute;rea)" itemValue=""/>
                            <f:selectItems value="#{reportsBean.list_area}" var="a" itemValue="#{a}"
                                           itemLabel="#{a}"/>
                            <p:ajax update="carrera plan_estudio asignatura"/>
                        </p:selectOneMenu>
                    </div>
                    <div class="col col-sm-6">
                        <p:outputPanel id="carrera">
                            #{reportsBean.updtate_carrera()}
                            <p:outputLabel for="carreraInput"
                                           styleClass="block"> Carrera </p:outputLabel> <br/>
                            <p:selectOneMenu value="#{reportsBean.carrera}"
                                             id="carreraInput"
                                             requiredMessage="Carrera: Es necesario seleccionar una Carrera"
                                             required="true" label="Carrera">
                                <f:selectItem itemLabel="(Seleccione una Carrera)" itemValue=""/>
                                <f:selectItems value="#{reportsBean.list_carrera}" var="c" itemValue="#{c}"
                                               itemLabel="#{c}"/>
                                <p:ajax update="plan_estudio asignatura"/>
                            </p:selectOneMenu>
                        </p:outputPanel>
                    </div>
                </div>
                <br/>
                <div class="row">
                    <div class="col col-sm-6">
                        <p:outputPanel id="plan_estudio">
                            #{reportsBean.update_plan_estudio()}
                            <p:outputLabel for="planEstudioInput"
                                           styleClass="block"> Plan de Estudio </p:outputLabel> <br/>
                            <p:selectOneMenu id="planEstudioInput" value="#{reportsBean.plan_estudio}"
                                             requiredMessage="Plan de Estudio: Es necesario seleccionar un Plan de Estudio"
                                             required="true" label="Plan de Estudio">
                                <f:selectItem itemLabel="(Seleccione un Plan de Estudio)" itemValue=""/>
                                <f:selectItems value="#{reportsBean.list_plan_estudio}" var="pe" itemValue="#{pe}"
                                               itemLabel="#{pe}"/>
                                <p:ajax update="asignatura"/>
                            </p:selectOneMenu>
                        </p:outputPanel>
                    </div>
                    <div class="col col-sm-6">
                        <p:outputPanel id="asignatura">
                            <p:outputLabel for="asignaturaInput"
                                           styleClass="block"> Asignatura </p:outputLabel> <br/>
                            #{reportsBean.update_Asignaturas()}
                            <p:selectOneMenu value="#{reportsBean.asignatura_Ms13d}"
                                             id="asignaturaInput"
                                             requiredMessage="Asignatura: Es necesario seleccionar una Asignatura"
                                             required="true" label="Asignatura">
                                <f:selectItem itemLabel="(Seleccione una Asignatura)" itemValue=""/>
                                <f:selectItems value="#{reportsBean.list_asignatura}" var="pe" itemValue="#{pe}"
                                               itemLabel="#{pe}"/>
                            </p:selectOneMenu>
                        </p:outputPanel>
                    </div>
                </div>
                <br/>

                <div style="float: right">
                    <p:commandButton title="PDF" style="margin-right: 10px" icon="pi pi-file-pdf"
                                     styleClass="ui-button ui-button-secondary" ajax="false"
                                     actionListener="#{reportsBean.print_rs4b_tipo1_PDF()}">
                    </p:commandButton>
                    <p:commandButton title="DOC" style="margin-right: 10px" icon="pi pi-file-word"
                                     styleClass="ui-button ui-button-secondary" ajax="false"
                                     actionListener="#{reportsBean.print_rs4b_tipo1_DOC()}">
                    </p:commandButton>
                    <p:commandButton title="RTF" style="margin-right: 10px" icon="pi pi-file"
                                     styleClass="ui-button ui-button-secondary" ajax="false"
                                     actionListener="#{reportsBean.print_rs4b_tipo1_RTF()}">
                    </p:commandButton>
                </div>

                <input type="hidden"
                       name="${_csrf.parameterName}"
                       value="${_csrf.token}"/>
            </h:form>

这是表单的图像,一旦填写完毕,按下生成 PDF 按钮,表单值被删除,并显示每个 selectOneMenu 的错误消息。

我希望你能帮我解决这个问题。预先感谢

jsf primefaces
1个回答
0
投票

感谢@JasperdeVries 的回复。我给你完整的解决方案。

可以使用ajax来解决这种情况。可以使用primefaces的下载组件。使用 Primefaces

StreamedContent
类,可以获取生成报告的流,然后通过
p:filedownloader
发送到视图。

视图看起来像这样:

<h:form id="form1">
                <p:growl id="messages" allowDismiss="true"/>
                <div class="row">
                    <div class="col col-sm-3">
                        <p:outputLabel for="idSearch"
                                       styleClass="block"> Identificaci&oacute;n </p:outputLabel>
                        <p:inputMask
                                id="idSearch"
                                mask="99999999999"
                                requiredMessage="ERROR: Es necesario un valor para establecer la b&uacute;squeda"
                                validatorMessage="ERROR: Idemtificaci&oacute;n no v&aacute;lida"
                                placeholder="Identificaci&oacute;n" value="#{reportsBean.idEstudiante}"
                                required="true"
                        />
                    </div>
                    <div class="col-sm-5">
                        <br/>
                        <p:commandButton title="PDF" style="margin-right: 10px" icon="pi pi-file-pdf"
                                         styleClass="ui-button ui-button-secondary" ajax="true" update="form1"
                                         actionListener="#{reportsBean.printCertCalifCursoAc('PDF')}">
                            <p:fileDownload value="#{reportsBean.file}"/>
                        </p:commandButton>
                        <p:commandButton title="DOCX" style="margin-right: 10px" icon="pi pi-file-word"
                                         styleClass="ui-button ui-button-secondary" ajax="true" update="form1"
                                         actionListener="#{reportsBean.printCertCalifCursoAc('DOCX')}">
                            <p:fileDownload value="#{reportsBean.file}"/>
                        </p:commandButton>
                        <p:commandButton title="RTF" style="margin-right: 10px" icon="pi pi-file"
                                         styleClass="ui-button ui-button-secondary" ajax="true" update="form1"
                                         actionListener="#{reportsBean.printCertCalifCursoAc('RTF')}">
                            <p:fileDownload value="#{reportsBean.file}"/>
                        </p:commandButton>
                    </div>
                </div>
                <input type="hidden"
                       name="${_csrf.parameterName}"
                       value="${_csrf.token}"/>
            </h:form>

然后,在 bean 中,准备好处理文件的基础,定义

StreamedContent
对象,并通过函数将报告数据发送到报告处理器。

public void printCertCalifCursoAc(String type){
        Map<String, Object> params = new java.util.HashMap<String, Object>();
        params.put("id", idEstudiante);
        String fileName = "Certificado de Calificaciones de Curso Académico - " + idEstudiante + "." + type.toLowerCase();
        String jasperPath = URL + "ms19d.jasper";
        FileType fileType = FileType.valueOf(type);
        try {
            file = reportUtil.processReport(params, jasperPath, fileName, fileType);
        } catch (JRException | IOException e) {
            throw new RuntimeException(e);
        }
    }

最后,考虑要处理的文件类型(本例中为 PDF、RTF 或 DOCX),处理文件。并且

StreamContent
被发送到Bean,然后发送到视图。

private StreamedContent getStreamedcontent(ByteArrayOutputStream outputStream, String fileName) throws IOException {
        InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
        SerializableSupplier<InputStream> supplier = () -> inputStream;
        StreamedContent streamedContent = DefaultStreamedContent.builder()
                .contentType("application/octet-stream")
                .name(fileName)
                .stream(supplier)
                .build();
        outputStream.flush();
        outputStream.close();
        inputStream.close();
        return streamedContent;
    }

    public StreamedContent processReport(Map<String, Object> params, String jasperpath, String fileName, FileType fileType) throws IOException, JRException {
        if (params == null) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "ERROR: Debe seleccionar o introducir un valor", "Error"));
        }
        String relativeWebPath = FacesContext.getCurrentInstance().getExternalContext().getRealPath(jasperpath);
        File file = new File(relativeWebPath);
        Connection con = connection.getConnectionInstance("org.postgresql.Driver", "jdbc:postgresql://localhost:5432/SIGENU_EaD", "postgres", "postgres");
        String filename = file.getPath();
        JasperPrint print = JasperFillManager.fillReport(filename, params, con);
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        switch (fileType) {
            case PDF -> JasperExportManager.exportReportToPdfStream(print, outputStream);
            case RTF -> {
                JRRtfExporter exporter = new JRRtfExporter();
                exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
                exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
                exporter.exportReport();
            }
            case DOCX -> {
                JRDocxExporter exporter = new JRDocxExporter();
                exporter.setParameter(JRExporterParameter.JASPER_PRINT, print);
                exporter.setParameter(JRExporterParameter.OUTPUT_STREAM, outputStream);
                exporter.exportReport();
            }
        }
        return getStreamedcontent(outputStream, fileName);
    }
© www.soinside.com 2019 - 2024. All rights reserved.