如何重置 TextFormField 中的错误消息?

Posted

技术标签:

【中文标题】如何重置 TextFormField 中的错误消息?【英文标题】:How to reset error message in TextFormField? 【发布时间】:2019-08-20 13:05:49 【问题描述】:

我知道这是一个简单的问题,但我没有找到如何做到这一点。当用户在字段中输入内容时,如何重置 TextFormField 中的错误消息。像 onchange 监听器之类的东西。我注意到 onChanged 在 TextField 中可用,但在 TextFormField 中不可用。我该怎么做?

final _email = Container(
  child: TextFormField(
    decoration: InputDecoration(labelText: email),
    keyboardType: TextInputType.emailAddress,
    controller: emailController,
    validator: _validateEmail,
    onSaved: (input) => _stringEmail = input.toLowerCase().trim(),
  ),
);

更新:我正在使用控制器为用户输入添加侦听器。但我只想重置错误消息而不是再次验证表单。这可能吗?我该怎么做?

  _resetEmailErrorMessage() 
    print("Second text field: $emailController.text");
    //replace clear to something that can reset the validation error message
    emailController.clear();
  

  @override
  void initState() 
    super.initState();

    //start listening to changes
    emailController.addListener(_resetEmailErrorMessage);
  

【问题讨论】:

【参考方案1】:

您可以使用Form的自动验证功能

如果您正在寻找此解决方案,

“只要你输入它就会验证你的输入并显示/隐藏错误”

Flutter 提供自动验证功能,您只需要在表单级别启用它。

    默认

    _autoValidate = false;

    表格

    body: Form( key: _formKey,
                autovalidate: _autoValidate,....)
    当用户按一次提交时启用它,
    if (_formKey.currentState.validate()) 
      // All Good
     else 
      // start auto validate
      setState(() 
        _autoValidate = true;
      );
    

更新:-

现在Form.autovalidate 已被弃用。所以使用

Form.autovalidateMode = AutovalidateMode.onUserInteraction 

【讨论】:

这确实解决了问题。再次验证表单会重置现在正确的字段的错误消息。 这是一个很好的解决方案,但请记住 autoValidate 已被弃用,您应该改用 AutovalidateMode.onUserInteraction【参考方案2】:

Form.autovalidate 已被弃用。使用Form.autovalidateMode = AutovalidateMode.onUserInteraction 可以在用户再次开始与表单字段交互时自动清除错误,而无需自己管理任何状态。

【讨论】:

是的,谢谢兄弟,这个新属性正是我们所需要的 :)【参考方案3】:

TextFormField 也有 onChanged 选项,您可以尝试通过 FormKey 重置表单验证

final _email = Container(
 child: TextFormField(
 decoration: InputDecoration(labelText: email),
  keyboardType: TextInputType.emailAddress,
  controller: emailController,
  validator: _validateEmail,
  onChanged: (value)
    formKey.currentState.reset();
  ,
  onSaved: (input) => _stringEmail = 
   input.toLowerCase().trim(),
  ),
);

【讨论】:

reset 方法清除all 错误的文本字段但只有一个被更改必须使用 如果你想清除错误警告那么你必须重置表单验证,我想目前没有其他办法【参考方案4】:

我建议使用控制器并听取用户输入。并且每当他输入内容时,您都可以再次验证()您的表单

【讨论】:

嗨。谢谢你。我听从了你的建议。但我不确定如何重置 TextFormField 中的验证错误消息。请帮忙 我不想再次验证表单,而是希望再次重置显示错误的文本表单字段(清除错误)。这可能吗? 是的,这是可能的。我会建议功能验证电子邮件做你的逻辑和测试。如果没有问题返回 null 。并在他输入内容时始终验证表单字段,您应该没问题 String validateEmail(String value) if (value.length == 0) return "too long"; 返回空值; TextFormField(验证器: validateEmail), 我们不能做类似“emailController.validate()”或“emailController.resetError()”的事情来代替验证整个表单吗?【参考方案5】:
// Somewhere in `State` declaration 
final formKey = GlobalKey<FormState>();
bool autovalidate = false;

@override
void build(BuildContext context) 
  return Form(
    key: formKey,
    autovalidate: autovalidate,
    child: Column(
      children: [
        TextFormField(
          ...
          validator: (value) 
            return (value == null || value.isEmpty) ? 'Cannot be empty' : null;
          
          onChanged: (value) 
            // Call this to refresh autovalidation result
            setState(() );
          
        ),
      ],
    ),
  );


void validate() 
  if(formKey.currentState.validate()) 
    // data is valid!
    return true;
   elsee 
    // Activate autovalidation
    autovalidate = true;
  
  return false;

【讨论】:

【参考方案6】:

我没有看到您的问题的任何答案。我也遇到过这样的情况,我希望身份验证表单的字段在用户更改为登录或注册后重置其验证错误。所以我添加了这个逻辑:

class _AuthFormState extends State<AuthForm> 
...
  var _formFlipped = false;                                   // THIS RIGHT HERE

  void _trySubmit() 
    final isValid = _formKey.currentState.validate();
    FocusScope.of(context).unfocus();
    ...
  

  @override
  Widget build(BuildContext context) 
    return 
      ...
            child: Form(
                ...
                  TextFormField(
                    key: ValueKey('email'),
                    validator: (value) 
                      if (_formFlipped) return null;          // THIS
                      if (value.isEmpty || !value.contains('@')) 
                        return 'Enter a valid email';
                      
                      return null;
                    ,
                    ...
                    RaisedButton(
                      child: Text(_isLogin ? 'Login' : 'Signup'),
                      onPressed: () 
                        setState(() 
                          _formFlipped = false;               // AND THIS
                        );
                        _trySubmit();
                      ,
                    ),
                    FlatButton(
                      child: Text(_isLogin
                          ? 'Create new account'
                          : 'I already have an account'),
                      onPressed: ()                          // THIS TOO
                        setState(() 
                          _isLogin = !_isLogin;
                          _formFlipped = true;
                          _formKey.currentState.validate();
                        );
                      ,
                    ),
        ...

Before & After.

编辑:

所以基本上你只需在所有字段验证器上强制传递null 即可清除消息。或者,正如Yogesh 指出的那样,您只需_formKey.currentState.reset(); 即可实现这一目标

但是如果您需要更精细的控制,这种方法对您很有帮助,因为您可以根据需要为不同的字段设置if (_formFlipped) return null;或类似的条件。

【讨论】:

【参考方案7】:

这是一种有效的形式。您可以尝试像这样验证表单:

_formKey.currentState.validate()

您需要在TextFormField 中定义验证字段。

【讨论】:

以上是关于如何重置 TextFormField 中的错误消息?的主要内容,如果未能解决你的问题,请参考以下文章

如何在TextFormField下方的errorText中添加图标?

Flutter TextFormField 控件

如何在reactjs中重置表单和登录错误消息

在 Flutter 小部件测试中,如何验证字段验证错误消息?

如何在 Flutter 中的 TextFormField 标签中添加红色星号

使用 textFormField 中的选项列表