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

Vaadin 23/24:如何通过正则实现客户端无效输入拦截?

在Vaadin 23/24中实现客户端输入拦截(替代原setPreventInvalidInput功能)

Vaadin 23+ 移除了setPreventInvalidInput方法,改用setAllowedCharPattern限制单字符输入,但后者仅校验单个字符,不会检查整体内容是否符合setPattern的完整规则(比如长度限制)。要实现原逻辑中客户端直接阻止无效输入的效果,可通过以下两种方式:

1. 直接为TextField添加客户端输入监听

通过executeJs方法注入JavaScript,实时校验输入内容是否匹配完整正则,不符合则回退到上一个有效状态:

TextField tf = new TextField();
tf.setPattern("\\d{0,5}"); // 限制最多5位数字
tf.getElement().executeJs("""
    // 保存上一次有效输入值
    this._lastValidValue = this.value;
    
    // 监听实时输入事件
    this.addEventListener('input', function(e) {
        const inputValue = e.target.value;
        const regex = new RegExp(`^${this.pattern}$`);
        if (!regex.test(inputValue)) {
            // 输入无效,回退到上一个有效值
            e.target.value = this._lastValidValue;
        } else {
            // 更新有效记录
            this._lastValidValue = inputValue;
        }
    });
    
    // 处理粘贴事件,防止粘贴无效内容
    this.addEventListener('paste', function(e) {
        e.preventDefault();
        const pastedText = e.clipboardData.getData('text');
        const newValue = this.value + pastedText;
        const regex = new RegExp(`^${this.pattern}$`);
        if (regex.test(newValue)) {
            this.value = newValue;
            this._lastValidValue = newValue;
        }
    });
""");

2. 封装自定义TextField组件(复用场景)

如果多个地方需要类似功能,可封装自定义组件,将拦截逻辑内置:

public class RestrictedTextField extends TextField {
    public RestrictedTextField() {}
    
    public RestrictedTextField(String pattern) {
        super();
        setPattern(pattern);
        setupInputRestrictions();
    }
    
    private void setupInputRestrictions() {
        getElement().executeJs("""
            const field = this;
            field._lastValidValue = field.value;
            
            // 输入事件拦截
            field.addEventListener('input', (e) => {
                const regex = new RegExp(`^${field.pattern}$`);
                if (!regex.test(e.target.value)) {
                    e.target.value = field._lastValidValue;
                } else {
                    field._lastValidValue = e.target.value;
                }
            });
            
            // 粘贴事件拦截
            field.addEventListener('paste', (e) => {
                e.preventDefault();
                const pastedText = e.clipboardData.getData('text');
                const newValue = field.value + pastedText;
                const regex = new RegExp(`^${field.pattern}$`);
                if (regex.test(newValue)) {
                    field.value = newValue;
                    field._lastValidValue = newValue;
                }
            });
        """);
    }
}

使用时直接实例化并传入正则即可:

RestrictedTextField tf = new RestrictedTextField("\\d{0,5}");

关键注意事项

  • 客户端拦截仅做用户体验优化,服务器端必须保留校验逻辑,防止恶意请求绕过客户端限制。
  • Java中定义正则时注意转义符(比如\\d对应JS中的\d),确保正则能在客户端正确解析。
  • 若正则包含复杂规则(比如分组、反向引用),需确认其在JavaScript环境中的兼容性。

内容的提问来源于stack exchange,提问作者Cédric O.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 21:00:48