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.
相关产品推荐
相关产品推荐

