问题 PrimeFaces

验证器未触发


因为fileLimit不存在于primefaces 3.4中,我正在尝试实现一个验证器,问题是从不调用方法validate。那是我的验证者:

@FacesValidator(value ="fileLimitValidator")
public class FileLimitValidator implements Validator {

    @Override
    public void validate(final FacesContext context, final UIComponent component,
            final Object value) throws ValidatorException {

        final String fileLimit = (String)component.getAttributes().get("fileLimit");
        final String size = (String)component.getAttributes().get("size");

        if (fileLimit!=null && size!=null) {
            if (Integer.valueOf(size) >= Integer.valueOf(fileLimit)) {
                FacesUtils.throwErrorExceptionFromComponent(component,"fichero_confidencialidad_error");
            }
        }
    }
}

在我的脸上,我试过了:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" >

        <f:validator validatorId="fileLimitValidator"/>
        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

和:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="fileLimitValidator">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

和:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="#{fileLimitValidator}">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

和:

    <p:fileUpload id="#{id}FileUpload"
        fileUploadListener="#{bean[metodoTratarFichero]}" mode="advanced"
        multiple="true" allowTypes="#{allowTypes}" showButtons="false"
        update="#{id}ListaDocs #{id}MsgError" auto="true"
        label="#{fileuploadmsg.label_boton}"
        invalidFileMessage="#{fileuploadmsg.tipo_incorrecto}" 
        validator="#{fileLimitValidator.validate}">

        <f:attribute name="fileLimit" value="#{fileLimit}"/>
        <f:attribute name="size" value="#{listaDocumentos.size}"/>
    </p:fileUpload>

但从未调用validate方法。这样做的正确方法是什么?


3303
2017-12-13 17:22


起源

stackoverflow.com/questions/3523998/... 我认为这就是它的样子。我们看起来是你尝试过的事情之一:(),确保你使用正确的导入。然后我会开始怀疑这个组件可能不支持它 - Aksel Willgert
我尝试了<f:validator validatorId =“fileLimitValidator”/>,其中h:inputText和方法被调用。 - Aksel Willgert


答案:


根据 FileUpload 和 FileUploadRenderer 源代码,验证器只在调用时调用 mode="simple" 已被使用(注意:这反过来要求 ajax="false" 在命令)。高级模式将不将上载的文件设置为组件的提交值,从而使其保留 null 直到调用listener方法。只要提交的值是 null,不调用验证器。

我不确定这是否是故意的。从理论上讲,应该可以设置 UploadedFile 作为提交的值并让验证者依赖它。您可能希望在以下位置创建增强报告 PrimeFaces发布跟踪器

与此同时,尽管它是一个 糟糕的做法,你最好的选择是真正执行验证 fileUploadListener 方法。您只需触发验证失败添加面部消息即可 FacesContext 如下:

if (fail) {
    context.validationFailed();
    context.addMessage(event.getComponent().getClientId(context), new FacesMessage(
        FacesMessage.SEVERITY_ERROR, messageSummary, messageDetail));
}

否则,您需要为其创建自定义渲染器 <p:fileUpload> 在此期间设置提交的值 decode() (但我不保证它会在实践中发挥作用,你可能会偶然发现一个奇怪的问题,这可能是PrimeFaces最初没有像那样实现它的原因)。

顺便说一句,您的第一次和第二次验证器尝试是正确的。第三次尝试只有在您使用时才有效 @ManagedBean 代替 @FacesValidator (这通常是在注射时进行的 @EJB 是强制性的 - 这是不可能的 @FacesValidator)。第四次尝试无效。


15
2017-12-13 20:39



@BalusC,为了验证(例如我需要至少上传一个文件):如何触发fileUploadListener事件,如果 p:fileUpload 在一个表格内,只有表格 commandButton 是给用户的吗? - jacktrades


要在模式高级(ajax)中验证所需的primefaces文件上载,可以使用:

<f:metadata>
    <f:event listener="#{bean.processValidations()}" type="postValidate" />
</f:metadata>

执行的地方 bean.processValidations() 方法将是这样的:

public void processValidations() {
        FacesContext context = FacesContext.getCurrentInstance();
        UIInput fileUploadComponent = fileUploadsBean.getFileUploadComponent();
        if (fileUploadComponent!=null && !isFileUploaded()) {
            fileUploadComponent.setValid(false);
            context.addMessage(fileUploadComponent.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR, messageSummary, messageDetail));
            context.validationFailed();
        }
    }

哪里 fileUploadsBean 将是一个REQUEST范围的CDI bean(不适用于标准的JSF ManagedBeans),你注入到你的bean processValidations() 方法定义,方法 fileUploadsBean.getFileUploadComponent() 返回primefaces文件上传组件(您将使用 <p:fileUpload binding="#{fileUploadsBean.fileUploadComponent}" ...> 为了那个原因)。方法 isFileUploaded() 将确定文件是否已上传(可能只是对从fileUploadListener填充的成员变量进行空检查)。

如果要突出显示文件上传按钮,您当然可以有条件地添加一个styleClass,然后可以使用它来添加红色边框。

styleClass="#{fileUploadsBean.fileUploadComponent.valid ? '' : 'validationFailed'}"

因此,Primefaces文件上载的验证失败消息将与所有其他jsf验证消息一起显示。您可能在维护验证消息的顺序方面存在问题(将始终在最后),但在用户处理来自不同字段的所有标准jsf验证消息以及您在辅助bean中的操作后,它仍然会显示失败的上载文件验证终于到了。


1
2017-11-10 16:23



最好的非标准验证方法IMO - teejay