You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何仅在点击指定按钮时触发XPages文本域的自定义验证器

问题:仅在特定按钮提交时触发XPages自定义验证器

我给xp:inputTextarea控件配置了验证规则:

<xp:inputTextarea id="inpRelPresentation"
    value="#{matterBean.matter.busRelations}"
    validator="#{matterValidators.valBusinessRelation}">    
    <xp:this.validators>
        <xp:validateRequired>
            <xp:this.message><![CDATA[#{javascript:xptI18NBean.getValue("matter.msg_valid_business_relation")}]]></xp:this.message>
        </xp:validateRequired>
    </xp:this.validators>
    <xp:this.required><![CDATA[#{javascript:return ( submittedBy('btnSendToCommitee'))}]]></xp:this.required>
</xp:inputTextarea>

其中required属性仅在点击ID为btnSendToCommittee的按钮时触发检查,但点击Save等其他按钮时,自定义验证器valBusinessRelation仍会被调用。

自定义验证器代码如下:

public void valBusinessRelation(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        System.out.println("start valBusinessRelation");
        if (value == null || StringUtil.isEmpty((String) value)) {
            System.out.println("do a return");
            return;
        }
        String trimmed = ((String) value).trim();
        if (trimmed.toString().replaceAll("\s+","").equals("")){
            System.out.println("empty after trimming etc, throw validator exception");
            String msgTxt = langBean.getValue("matter.msg_valid_business_relation");
            FacesMessage msg = new FacesMessage(msgTxt, msgTxt);
            msg.setSeverity(FacesMessage.SEVERITY_ERROR);
            throw new ValidatorException(msg);
        }
    }

需要让该自定义验证器仅在点击btnSendToCommittee按钮时被调用,但submittedBy('btnSendToCommitee')是SSJS检查,验证器调用用的是EL,不知道如何实现,也未找到通过validator-id调用验证器的完整示例。


解决方案1:在Java验证器内部判断提交按钮

直接在验证器逻辑开头检查当前请求是否由目标按钮发起,非目标按钮提交则跳过验证。

修改后的Java验证器代码:

public void valBusinessRelation(FacesContext context, UIComponent component, Object value) throws ValidatorException {
    // 检查请求是否来自目标按钮(注意:若按钮在命名容器内,需使用完整客户端ID)
    HttpServletRequest request = (HttpServletRequest) context.getExternalContext().getRequest();
    if (!request.getParameterMap().containsKey("btnSendToCommittee")) {
        return; // 非目标按钮提交,跳过验证
    }

    // 原有验证逻辑
    System.out.println("start valBusinessRelation");
    if (value == null || StringUtil.isEmpty((String) value)) {
        System.out.println("do a return");
        return;
    }
    String trimmed = ((String) value).trim();
    if (trimmed.replaceAll("\\s+", "").isEmpty()){
        System.out.println("empty after trimming etc, throw validator exception");
        String msgTxt = langBean.getValue("matter.msg_valid_business_relation");
        FacesMessage msg = new FacesMessage(msgTxt, msgTxt);
        msg.setSeverity(FacesMessage.SEVERITY_ERROR);
        throw new ValidatorException(msg);
    }
}

提示:可通过查看页面源码获取按钮的实际客户端ID(若存在命名容器前缀,比如view:_id1:btnSendToCommittee)。

解决方案2:用SSJS动态调用验证器

将验证器绑定改为SSJS,仅在目标按钮提交时执行验证逻辑,和required属性的判断逻辑保持一致:

修改xp:inputTextarea的validator属性:

<xp:inputTextarea id="inpRelPresentation"
    value="#{matterBean.matter.busRelations}">    
    <xp:this.validators>
        <xp:validateRequired>
            <xp:this.message><![CDATA[#{javascript:xptI18NBean.getValue("matter.msg_valid_business_relation")}]]></xp:this.message>
        </xp:validateRequired>
    </xp:this.validators>
    <xp:this.required><![CDATA[#{javascript:return ( submittedBy('btnSendToCommitee'))}]]></xp:this.required>
    <xp:this.validator><![CDATA[#{javascript:
        if (submittedBy('btnSendToCommitee')) {
            matterValidators.valBusinessRelation(facesContext, component, value);
        }
    }]]></xp:this.validator>
</xp:inputTextarea>

这种方式无需处理客户端ID前缀问题,逻辑更直观。

解决方案3:通过validator-id注册并条件渲染

适合需要复用验证器的场景,需先在faces-config.xml注册验证器:

<validator>
    <validator-id>valBusinessRelation</validator-id>
    <validator-class>com.yourpackage.ValBusinessRelation</validator-class>
</validator>

注意:需将原Bean中的验证方法改为独立的Validator实现类:

public class ValBusinessRelation implements Validator {
    @Override
    public void validate(FacesContext context, UIComponent component, Object value) throws ValidatorException {
        // 原有验证逻辑
    }
}

然后在页面中通过xp:validator标签,结合rendered属性控制验证器是否生效:

<xp:inputTextarea id="inpRelPresentation"
    value="#{matterBean.matter.busRelations}">    
    <xp:this.validators>
        <xp:validateRequired>
            <xp:this.message><![CDATA[#{javascript:xptI18NBean.getValue("matter.msg_valid_business_relation")}]]></xp:this.message>
        </xp:validateRequired>
        <xp:validator validatorId="valBusinessRelation" rendered="#{javascript:submittedBy('btnSendToCommitee')}"/>
    </xp:this.validators>
    <xp:this.required><![CDATA[#{javascript:return ( submittedBy('btnSendToCommitee'))}]]></xp:this.required>
</xp:inputTextarea>

内容的提问来源于stack exchange,提问作者Patrick Kwinten

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 08:31:07