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

发布于 2025-02-08 21:44:08 字数 2000 浏览 2 评论 0原文

我有两个TextFormFields,它专注于密码字段在验证错误上,即使电子邮件字段已经有错误&在密码字段之前。

知道这里怎么了吗?


              //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;
}

忽略这个愚蠢的段落:(这只是一堆文字,以说明我添加了更多问题细节,即使不是必需的,也不可用)

I've two TextFormFields, it focus on the password field on validation error, even if email field has error already & comes before password field.

enter image description here
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])?)*
quot;;
  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,}
quot;;
  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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

转身以后 2025-02-15 21:44:08

表单窗口小部件将其包装,并仅在按钮上单击以下单击时进行验证。

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'),
            ),
          ),
        ],
      ),
    );
  }
}

检查一下是否有详细的说明

https://docs.flutter.dev/cookbook/cookbook/forms/forms/validation

如果是空的,请重点请求。如果两者都是null,那将始终保持关注密码字段

Wrap it with a form widget and validate it only on a button click like the following.

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

Edit

Please remove focus request if it's null. That will always keep the focus on password field if both are null

心奴独伤 2025-02-15 21:44:08

问题

您有2个验证器,最后一个将作用。这意味着,如果您的两个TextFormField不有效,那么最后一个总是最后一个工作,而您的焦点则放在最后一个。

解决方案

如果Email FocusNode并未像以下那样的重点,请检查另一个内部的另一个焦点node和焦点密码区域

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

Problem

You have 2 validators and the last one will work the last. That means if your both TextFormField is not valid the last one always works last and your focus goes to the last one.

Solution

check the other focusNode inside of another and focus password area if email focusNode has not focused like below

//Password
TextFormField(
  controller: _passwordController,
  focusNode: _passwordFocus,
  validator: (value) {
    String? err = validatePassword(value);
    if (err != null) {
        if(!_emailFocus.hasFocus){
          _passwordFocus.requestFocus();
        }
    }
    return err;
  },           
),    
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文