Flutter问题:文本编辑控制器数据无法传递至自定义验证构建器
解决密码验证器无法获取控制器最新值的问题
我想把密码输入框控制器的字符串传递给自定义的Validation Builder验证器,但测试发现,文本编辑控制器里的字符串没法传到验证构建器里,不过通过按钮访问该控制器的数据是正常的。我用的是form_validator包。
原代码片段
密码输入框部分:
child: TextFormField( controller: _repeatPassController, validator: ValidationBuilder(requiredMessage: "Bu alan gereklidir") .repeatPassword(passController.text) .build(), obscureText: true, decoration: InputDecoration( border: OutlineInputBorder(), labelText: 'Tekrar Şifre', hintText: 'Güvenli bir şifre giriniz'), ),
consts.dart中的验证器定义:
import 'package:form_validator/form_validator.dart'; class Consts { static final emailValidator = ValidationBuilder( requiredMessage: "Bu alan gereklidir", ).email("E-mail geçerli değil!").build(); static final passValidator = ValidationBuilder(requiredMessage: "Bu alan gereklidir!") .password() .build(); } extension CustomValidationBuilder on ValidationBuilder { password() => add((value) { if (value == null || value.isEmpty) { return "Şifre gereklidir"; } if (value.length < 5) { return 'Şifreniz en az 5 karakter olmalıdır!'; } return null; }); } extension CustomValidationBuilderRepeatPassword on ValidationBuilder { ///检查重复密码是否匹配 ///不匹配则返回错误信息 repeatPassword(String password) => add((value) { if (value == null || value.isEmpty) { return "Bu alan gereklidir"; } if (value != password) { print(value + " value"); ///输出:"myvalue value" print(password + " password"); ///输出:" password"(password为空) return 'Şifreler eşleşmiyor!'; } return null; }); }
问题原因
核心问题是验证器初始化时就固定了密码值。Widget构建阶段,ValidationBuilder().repeatPassword(passController.text)会立即读取此时passController的text(初始为空),并把这个空值存在验证逻辑里。之后用户输入密码,控制器的text更新了,但验证器里保存的还是最初的空值,所以对比时永远不匹配,打印里password显示为空。而按钮点击是实时读取passController.text,所以能拿到最新值。
解决方案
修改自定义的repeatPassword扩展方法,让它接收TextEditingController而非String,这样在验证时可以实时获取控制器的最新text值。
1. 更新consts.dart中的验证器扩展
import 'package:form_validator/form_validator.dart'; import 'package:flutter/material.dart'; // 需导入以使用TextEditingController class Consts { static final emailValidator = ValidationBuilder( requiredMessage: "Bu alan gereklidir", ).email("E-mail geçerli değil!").build(); static final passValidator = ValidationBuilder(requiredMessage: "Bu alan gereklidir!") .password() .build(); } extension CustomValidationBuilder on ValidationBuilder { password() => add((value) { if (value == null || value.isEmpty) { return "Şifre gereklidir"; } if (value.length < 5) { return 'Şifreniz en az 5 karakter olmalıdır!'; } return null; }); } extension CustomValidationBuilderRepeatPassword on ValidationBuilder { /// 检查重复密码是否匹配,不匹配返回错误信息 repeatPassword(TextEditingController passwordController) => add((value) { if (value == null || value.isEmpty) { return "Bu alan gereklidir"; } final password = passwordController.text; // 实时读取最新密码 if (value != password) { print("$value value"); print("$password password"); return 'Şifreler eşleşmiyor!'; } return null; }); }
2. 修改TextFormField的validator参数
直接传递控制器实例,而不是它的text属性:
child: TextFormField( controller: _repeatPassController, validator: ValidationBuilder(requiredMessage: "Bu alan gereklidir") .repeatPassword(passController) // 传入控制器 .build(), obscureText: true, decoration: InputDecoration( border: OutlineInputBorder(), labelText: 'Tekrar Şifre', hintText: 'Güvenli bir şifre giriniz'), ),
可选优化:实时触发验证
如果想让重复密码输入框在用户修改原密码时自动验证,可以给passController添加监听,在initState中加入:
@override void initState() { super.initState(); passController.addListener(() { // 假设你有表单的GlobalKey:_formKey if (_formKey.currentState != null) { _formKey.currentState!.validate(); } }); } @override void dispose() { passController.dispose(); _repeatPassController.dispose(); super.dispose(); }
内容的提问来源于stack exchange,提问作者enes durmuş
相关产品推荐
相关产品推荐

