Dart/Flutter表单校验时如何对比当前输入值与上一次输入的日期值
Flutter 日期先后校验实现方案
你现有代码只做了输入长度校验,要实现「当前输入日期晚于上一次成功录入日期才通过校验」的逻辑,按以下步骤修改即可:
- 首先在表单对应的State类中新增一个可空的
DateTime类型变量,持久化存储上一次成功保存的日期,初始值为null(首次录入无历史值时不触发对比)。 - 新增适配当前
JJ-MM-AAAA(日-月-年)格式的日期解析方法,把输入字符串转为可直接比较大小的DateTime对象,同时拦截长度达标但实际非法的日期值(比如32-13-2024、31-04-2024这类不符合日历规则的输入)。 - 扩展原有
validator逻辑,在长度校验之后追加日期合法性校验、历史日期对比校验。 - 修改
onSaved回调,在保存输入值的同时同步更新存储上一次日期的变量,供下一次校验使用。
关键代码实现
1. 新增状态变量与日期解析工具方法
在表单组件的State类中添加以下代码:
// 存储上一次成功录入的日期 DateTime? _lastSavedDate; /// 解析日-月-年格式的日期字符串,非法格式返回null DateTime? _parseDDMMYYYY(String input) { try { final parts = input.split('-'); if (parts.length != 3) return null; final day = int.parse(parts[0]); final month = int.parse(parts[1]); final year = int.parse(parts[2]); final parsedDate = DateTime(year, month, day); // 反向校验,避免DateTime自动进位非法日期(比如31-04自动转成01-05) if (parsedDate.day != day || parsedDate.month != month || parsedDate.year != year) { return null; } return parsedDate; } catch (_) { return null; } }
2. 修改TextFormField的校验与保存逻辑
替换原有TextFormField的validator和onSaved部分代码:
TextFormField( autofocus: true, keyboardType: TextInputType.datetime, controller: _controller, decoration: const InputDecoration( hintText: 'JJ-MM-AAAA', counterText: '', ), inputFormatters: [ FilteringTextInputFormatter.allow(RegExp(r'[0-9-]')), LengthLimitingTextInputFormatter(10), ], onSaved: (val) { final validDate = _parseDDMMYYYY(val!); taskItems.addItem(val); // 保存成功后更新上一次录入的日期 _lastSavedDate = validDate; }, validator: (val) { // 原有长度校验 if (val == null || val.length < 10) { return 'Entre une date valide'; } // 校验日期本身是否符合日历规则 final inputDate = _parseDDMMYYYY(val); if (inputDate == null) { return 'Entre une date valide'; } // 存在历史录入值时,校验当前日期是否晚于历史值 if (_lastSavedDate != null && !inputDate.isAfter(_lastSavedDate!)) { return 'La date doit être postérieure à la dernière date enregistrée'; } return null; }, )
3. 提交按钮逻辑无需调整
原有ElevatedButton的提交逻辑可以直接复用,校验通过后会自动执行保存、重置表单的流程。
实现说明
- 日期对比直接用
DateTime内置的isAfter方法,会自动处理闰年、大小月、跨年跨月的计算逻辑,比手动拆分数字对比可靠性高很多。 - 日期解析加了反向校验,避免Dart的DateTime构造函数自动把非法日期进位为合法日期,导致非法输入漏过校验。
- 首次录入时
_lastSavedDate为null,不会触发日期对比逻辑,符合首次录入无参考值的使用场景。
内容的提问来源于stack exchange,提问作者milano zz
相关产品推荐
相关产品推荐

