如何在文本表单字段具有有效数据 Flutter 之前禁用按钮

How to disable button until text form field has valid data Flutter

我想做的是在文本表单字段有效之前禁用提升按钮。然后一旦数据有效,应该启用提升按钮。我已经查看了几个 SO 线程和关于 Google 的几篇文章,内容涉及如何在验证文本表单字段之前禁用按钮。他们都关注文本表单字段是否为空,这不是我在这里要问的。我正在使用正则表达式来确定用户是否输入了有效的电子邮件地址。只有当输入的数据是有效的电子邮件时,数据才被视为有效。那是我希望按钮启用的时候。如果我尝试在 validateEmail 方法中使用布尔值调用 setState,我会收到错误消息:

在构建过程中调用了 setState() 或 markNeedsBuild()。

如有任何帮助,我们将不胜感激。谢谢。

class ResetPasswordForm extends StatefulWidget {
  const ResetPasswordForm({Key? key}) : super(key: key);

  @override
  _ResetPasswordFormState createState() => _ResetPasswordFormState();
}

class _ResetPasswordFormState extends State<ResetPasswordForm> {
  final _formKey = GlobalKey<FormState>();
  final TextEditingController _emailController = TextEditingController();

  String? validateEmail(String? value) {
    String pattern = ValidatorRegex.emailAddress;
    RegExp regex = RegExp(pattern);
    if (value == null || value.isEmpty || !regex.hasMatch(value)) {
      return ValidatorString.enterValidEmail;
    } else {
      return null;
    }
  }

  @override
  void dispose() {
    _emailController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Form(
          key: _formKey,
          child: TextFormField(
            controller: _emailController,
            validator: (value) => validateEmail(value),
          ),
        ),
        ElevatedButton(
          onPressed: () {
            if (_formKey.currentState!.validate()) {
              Auth().resetPassword(
                context,
                _emailController.text.trim(),
              );
            }
          },
          child: const Text('Reset Password'),
        ),
      ],
    );
  }
}

大多数小部件的启用和禁用功能是相同的

设置onPressed属性如下图

onPressed : null returns 一个禁用的小部件,同时 onPressed: (){}onPressed: _functionName returns 已启用小部件

在这种情况下,它将是这样的:

ElevatedButton(
          onPressed: () {
            if (_formKey.currentState!.validate()) {
              Auth().resetPassword(
                context,
                _emailController.text.trim(),
              );
            } else {
              print('disabled');
            }
          },
          child: const Text('Reset Password'),
        ),

你可以这样做:

class ResetPasswordForm extends StatefulWidget {
  const ResetPasswordForm({Key? key}) : super(key: key);

  @override
  _ResetPasswordFormState createState() => _ResetPasswordFormState();
}

class _ResetPasswordFormState extends State<ResetPasswordForm> {
  final _formKey = GlobalKey<FormState>();
  final TextEditingController _emailController = TextEditingController();
 final bool _isValidated = false;

  String? validateEmail(String? value) {
    String pattern = ValidatorRegex.emailAddress;
    RegExp regex = RegExp(pattern);
    if (value == null || value.isEmpty || !regex.hasMatch(value)) {
      return ValidatorString.enterValidEmail;
    } else {
      setState(){
        _isValidated = true;
      }
      return null;
    }
  }

  @override
  void dispose() {
    _emailController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Form(
          key: _formKey,
          child: TextFormField(
            controller: _emailController,
            validator: (value) => validateEmail(value),
          ),
        ),
        ElevatedButton(
          onPressed:_isValidated
              ? () {
                  //do stuff
                }
              : null,,
          child: const Text('Reset Password'),
        ),
      ],
    );
  }
}
    

如果 onPressed 为 null,则按钮被禁用。

首先,将逻辑移动到命名函数中

void _sendData (){
 if (_formKey.currentState!.validate()) { 
  Auth().resetPassword( context, 
  _emailController.text.trim(), );
}

现在处于按下状态

onpressed: _emailController.text.trim.isNotEmpty?_sendData : null;

最好为此创建一个表单密钥

final formGlobalKey = GlobalKey <FormState> ();

将其分配为如下形式:

Form(
    key: formGlobalKey,

现在您只需检查验证,例如:

ElevatedButton(
        style: style,
        onPressed: formGlobalKey.currentState==null?null: formGlobalKey.currentState!.validate()? () {
This is body of button} : null,
            child: const Text('Enabled'),
          ),

**如果您没有使用第一个条件(formGlobalKey.currentState==null?),它将带您走向空异常**