简体   繁体   English

Flutter Textformfield 验证器将最后一个 TextFormfield 集中在验证错误上,而不是第一个

[英]Flutter Textformfield validator Focuses Last TextFormfield on validation error instead of first

I've two TextFormFields, it focus on the password field on validation error, even if email field has error already & comes before password field.我有两个 TextFormFields,它专注于验证错误的密码字段,即使电子邮件字段已经有错误并且在密码字段之前。

在此处输入图像描述 Any idea what's going wrong here?知道这里出了什么问题吗?


              //Email
              TextFormField(
              controller: _emailController,
              focusNode: _emailFocus,         
              validator: (value) {
                String? err = validateEmail(value);
                if (err != null) {
                  _emailFocus.requestFocus();
                }
                return err;
              },
            ),
           //Password
            TextFormField(
              controller: _passwordController,
              focusNode: _passwordFocus,
              validator: (value) {
                String? err = validatePassword(value);
                if (err != null) {
                  _passwordFocus.requestFocus();
                }
                return err;
              },           
           ),    
String? validateEmail(String? value) {
  String pattern = r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]"
      r"{0,253}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]"
      r"{0,253}[a-zA-Z0-9])?)*$";
  RegExp regex = RegExp(pattern);
  if (value == null || value.isEmpty || !regex.hasMatch(value)) {
    return 'Enter a valid email address';
  } else {
    return null;
  }
}

String? validatePassword(String? value) {
  String pattern = r"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$";
  RegExp regex = RegExp(pattern);
  if (value == null || value.isEmpty) {
    return 'Required';
  }
  if (value.length < 8) {
    return "Length should be 8 or more";
  }
  if (!regex.hasMatch(value)) {
    return "Must contain atleast 1 uppecase, 1 lowercase, 1 special character,";
  }
  return null;
}

Ignore this silly paragraph:(This is just bunch of text, to tell SO that I have added more question details even if it is NOT required and NOT available)忽略这个愚蠢的段落:(这只是一堆文字,告诉我我已经添加了更多的问题细节,即使它不是必需的并且不可用)

Wrap it with a form widget and validate it only on a button click like the following.form小部件包装它,并仅在单击按钮时对其进行验证,如下所示。

import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    const appTitle = 'Form Validation Demo';

    return MaterialApp(
      title: appTitle,
      home: Scaffold(
        appBar: AppBar(
          title: const Text(appTitle),
        ),
        body: const MyCustomForm(),
      ),
    );
  }
}

// Create a Form widget.
class MyCustomForm extends StatefulWidget {
  const MyCustomForm({super.key});

  @override
  MyCustomFormState createState() {
    return MyCustomFormState();
  }
}

// Create a corresponding State class.
// This class holds data related to the form.
class MyCustomFormState extends State<MyCustomForm> {
  // Create a global key that uniquely identifies the Form widget
  // and allows validation of the form.
  //
  // Note: This is a GlobalKey<FormState>,
  // not a GlobalKey<MyCustomFormState>.
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    // Build a Form widget using the _formKey created above.
    return Form(
      key: _formKey,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          TextFormField(
            // The validator receives the text that the user has entered.
            validator: (value) {
              if (value == null || value.isEmpty) {
                return 'Please enter some text';
              }
              return null;
            },
          ),
          Padding(
            padding: const EdgeInsets.symmetric(vertical: 16.0),
            child: ElevatedButton(
              onPressed: () {
                // Validate returns true if the form is valid, or false otherwise.
                if (_formKey.currentState!.validate()) {
                  // If the form is valid, display a snackbar. In the real world,
                  // you'd often call a server or save the information in a database.
                  ScaffoldMessenger.of(context).showSnackBar(
                    const SnackBar(content: Text('Processing Data')),
                  );
                }
              },
              child: const Text('Submit'),
            ),
          ),
        ],
      ),
    );
  }
}

Check this for a detailed explanation https://docs.flutter.dev/cookbook/forms/validation检查此以获取详细说明https://docs.flutter.dev/cookbook/forms/validation

Edit编辑

Please remove focus request if it's null.如果它为空,请删除焦点请求。 That will always keep the focus on password field if both are null如果两者都为空,那将始终关注密码字段

Problem问题

You have 2 validators and the last one will work the last.您有 2 个验证器,最后一个将在最后一个工作。 That means if your both TextFormField is not valid the last one always works last and your focus goes to the last one.这意味着,如果您的两个 TextFormField 都无效,则最后一个总是最后一个,您的焦点将转到最后一个。

Solution解决方案

check the other focusNode inside of another and focus password area if email focusNode has not focused like below如果电子邮件 focusNode 没有像下面那样聚焦,请检查另一个和聚焦密码区域内的另一个 focusNode

//Password
TextFormField(
  controller: _passwordController,
  focusNode: _passwordFocus,
  validator: (value) {
    String? err = validatePassword(value);
    if (err != null) {
        if(!_emailFocus.hasFocus){
          _passwordFocus.requestFocus();
        }
    }
    return err;
  },           
),    

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM