如何清除Flutter中TextFormField中的错误消息

时间:2019-04-23 11:56:34

标签: flutter

在我的代码中,我验证电话号码。如果电话号码不正确-我会显示错误消息。但是,当用户开始编辑号码时,我想隐藏此错误消息。

我找到了currentState.reset()的解决方案,但这似乎不是一个好的解决方案。我必须处理保存文本和光标位置的问题。而且我还有一个小神器。通常,当我按住退格键时,它将一一删除符号。如果在显示错误消息时执行此操作-错误消息消失并且仅删除一个符号。

有人知道这种情况的正确解决方案吗?

final TextEditingController controller = TextEditingController();
final RegExp _phoneRegex = RegExp(r"^\+{1}\d{10, 15}\$");
bool isError = false;
TextSelection currentPosition;

return Column(
  children: <Widget>[
    Form(
        key: _textKey,
        child: TextFormField(
          controller: controller,
          validator: (str) {
            isError = true;
            if (str.isEmpty) {
              return err_empty_field;
            } else if (!_phoneRegex.hasMatch(str)) {
              return err_invalid_phone;
            }
            isError = false;
          },
        ),
        onChanged: () {
          if (controller.selection.start < 0 &&
              controller.text.length > 0) {
            TextSelection position =
                controller.text.length > currentPosition.start
                    ? currentPosition
                    : TextSelection.fromPosition(
                        TextPosition(offset: controller.text.length));
            controller.selection = position;
          }
          if (isError) {
            isError = false;
            currentPosition = controller.selection;
            if (currentPosition.start > controller.text.length) {
              currentPosition = TextSelection.fromPosition(
                  TextPosition(offset: controller.text.length));
            }
            String currentText = controller.text;
            _textKey.currentState.reset();
            controller.text = currentText;
            controller.selection = currentPosition;
          }
        },
      ),
    RaisedButton(
      onPressed: () {
        _textKey.currentState.validate();
      },
      child: Text(login),
    )
  ],
);

6 个答案:

答案 0 :(得分:10)

这是解决此问题的合适方法。

您实际上不需要使用onChanged或引起副作用的任何技巧,我通过创建一个初始化为false的类属性来解决了该问题:

bool _autovalidate = false;

表单小部件具有命名属性autovalidate。您应该将前一个布尔值传递给它:

Form(
  key: _textKey,
  autovalidate: _autovalidate,
  ... 
)

在提交按钮onPressed()方法中,如果表单为_autovalidate,则应将true布尔值更新为invalid,这将使表单自动验证每个onChanged调用中的TextFormField:

RaisedButton(
  onPressed: () {
    if (_textKey.currentState.validate()) {
      print('valid');
    } else {
      print('invalid');
      setState(() => _autoValidate = true);
    }
  },
  child: Text(login),
)

我希望它对某人有所帮助。

EDIT(2020年11月)

autovalidate在v1.19.0之后被弃用。
而是使用autovalidateMode

Form(
  autovalidateMode: AutovalidateMode.onUserInteraction`.
  ...
)

答案 1 :(得分:3)

这里的问题是errorTextvalidator的{​​{1}}字段自动管理。同时,简单的解决方案是手动处理TextFormField

步骤1:创建

  • 字符串字段errorText初始化为_errorText。该字段将包含需要显示的错误消息。
  • 布尔字段null初始化为_error。如果有错误,则提交的字段为false,否则为true

第2步:

  • false分配给_errorText

第3步(重要):

  • 确保TextFormField TextFormField返回一个validator值。

  • 在此处处理验证并将正确的错误消息分配给null

  • 相应地更新_errorText状态。

第4步(重要):

  • 重置_error_errorText。开始编辑后,这将立即从字段中删除错误。

第5步:

  • _error中触发字段验证并管理您的代码流...
onFieldSubmitted

答案 2 :(得分:2)

2021 年 1 月

...

AutovalidateMode _autoValidate = AutovalidateMode.disabled;
Form(
  key: _textKey,
  autovalidateMode: _autovalidate,
  ... 
)
RaisedButton(
  onPressed: () {
    if (_textKey.currentState.validate()) {
      print('valid');
    } else {
      print('invalid');
      setState(() => _autoValidate = AutovalidateMode.always);
    }
  },
  child: Text("login"),
)

答案 3 :(得分:1)

我已经实现了以下两项功能:

1)编辑时隐藏错误消息

2)按下登录按钮时验证输入字段

  

注意:我已评论电话号码正则表达式并进行了验证   字符串长度<10位数以进行测试。

fn main() {
    let mut s = String::from("hello world");

    {
        let word = first_word(&s);
    }

    s.clear();
}

答案 4 :(得分:1)

我找到了可行且更简单的方法

final _textKey = GlobalKey<FormState>();
final TextEditingController _controller = TextEditingController();

Widget _getPhoneInputForm() {
  final RegExp _phoneRegex = RegExp(r"^\+{1}\d{10,17}");
  bool isError = false;
  bool isButtonPressed = false;

  return Column(
    crossAxisAlignment: CrossAxisAlignment.center,
    mainAxisSize: MainAxisSize.max,
    mainAxisAlignment: MainAxisAlignment.center,
    children: <Widget>[
      Padding(
        padding: EdgeInsets.symmetric(horizontal: 36.0),
        child: Form(
          key: _textKey,
          child: TextFormField(
            keyboardType: TextInputType.phone,
            decoration: InputDecoration(
                hintText: hint_enter_phone,
                contentPadding: EdgeInsets.all(24.0),
                fillColor: Colors.blueGrey.withOpacity(0.3),
                filled: true,
                border: OutlineInputBorder(
                    borderRadius: BorderRadius.all(Radius.circular(16.0)),
                    borderSide: BorderSide(color: Colors.blueGrey))),
            controller: _controller,
            validator: (str) {
              if (!isButtonPressed) {
                return null;
              }
              isError = true;
              if (str.isEmpty) {
                return err_empty_field;
              } else if (!_phoneRegex.hasMatch(str)) {
                return err_invalid_phone;
              }
              isError = false;
            },
            onFieldSubmitted: (str) {
              if (_textKey.currentState.validate()) _phoneLogin();
            },
          ),
          onChanged: () {
            isButtonPressed = false;
            if (isError) {
              _textKey.currentState.validate();
            }
          },
        ),
      ),
      RaisedButton(
        color: Colors.teal,
        textColor: Colors.white,
        onPressed: () {
          isButtonPressed = true;
          if (_textKey.currentState.validate()) _phoneLogin();
        },
        child: Text(login),
      )
    ],
  );
}

答案 5 :(得分:0)

这是一个例子,我认为没有必要执行onchange(),函数validate name可以完成工作...

 String validateName(String value) {
    String patttern = r'(^[a-zA-Z ]*$)';
    RegExp regExp = new RegExp(patttern);
    if (value.length == 0) {
      return "Name is Required";
    } else if (!regExp.hasMatch(value)) {
      return "Name must be a-z and A-Z";
    }
    return null;
  }

  TextFormField(
                              controller: _lastname, validator: validateName ,
                              //initialValue: widget.contact.last_name,
                              decoration:
                                  InputDecoration(labelText: 'Last name'),
                            ),

void Save() {
 if (_keyForm.currentState.validate()) {
      // No any error in validation
      _keyForm.currentState.save(); 
................
}