flutter-form

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Flutter Form Validation

Flutter 表单验证

Goal

目标

Implements stateful form validation in Flutter using
Form
,
TextFormField
, and
GlobalKey<FormState>
. Manages validation state efficiently without unnecessary key regeneration and handles user input validation workflows. Assumes a pre-existing Flutter environment with Material Design dependencies available.
在Flutter中使用
Form
TextFormField
GlobalKey<FormState>
实现有状态的表单验证。高效管理验证状态,避免不必要的键重新生成,并处理用户输入验证流程。假设已存在具备Material Design依赖的Flutter环境。

Decision Logic

决策逻辑

When implementing form validation, follow this decision tree to determine the flow of state and UI updates:
  1. User triggers submit action:
    • Call
      _formKey.currentState!.validate()
      .
  2. Does
    validate()
    return
    true
    ?
    • Yes (Valid): Proceed with data processing (e.g., API call, local storage). Trigger success UI feedback (e.g.,
      SnackBar
      , navigation).
    • No (Invalid): The
      FormState
      automatically rebuilds the
      TextFormField
      widgets to display the
      String
      error messages returned by their respective
      validator
      functions. Halt submission.
在实现表单验证时,请遵循以下决策树来确定状态和UI更新流程:
  1. 用户触发提交操作:
    • 调用
      _formKey.currentState!.validate()
  2. validate()
    是否返回
    true
    • 是(有效): 继续进行数据处理(例如API调用、本地存储)。触发成功UI反馈(例如
      SnackBar
      、页面导航)。
    • 否(无效):
      FormState
      会自动重建
      TextFormField
      组件,以显示各自
      validator
      函数返回的错误提示字符串。终止提交流程。

Instructions

操作步骤

  1. Initialize the Stateful Form Container Create a
    StatefulWidget
    to hold the form. Instantiate a
    GlobalKey<FormState>
    exactly once within the
    State
    class to prevent resource-expensive key regeneration during
    build
    cycles.
    dart
    import 'package:flutter/material.dart';
    
    class CustomValidatedForm extends StatefulWidget {
      const CustomValidatedForm({super.key});
    
      
      State<CustomValidatedForm> createState() => _CustomValidatedFormState();
    }
    
    class _CustomValidatedFormState extends State<CustomValidatedForm> {
      // Instantiate the GlobalKey once in the State object
      final _formKey = GlobalKey<FormState>();
    
      
      Widget build(BuildContext context) {
        return Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              // Form fields will be injected here
            ],
          ),
        );
      }
    }
  2. Implement TextFormFields with Validation Logic Inject
    TextFormField
    widgets into the
    Form
    's widget tree. Provide a
    validator
    function for each field.
    dart
    TextFormField(
      decoration: const InputDecoration(
        hintText: 'Enter your email',
        labelText: 'Email',
      ),
      validator: (String? value) {
        if (value == null || value.isEmpty) {
          return 'Please enter an email address';
        }
        if (!value.contains('@')) {
          return 'Please enter a valid email address';
        }
        // Return null if the input is valid
        return null; 
      },
      onSaved: (String? value) {
        // Handle save logic here
      },
    )
  3. Implement the Submit Action and Validation Trigger Create a button that accesses the
    FormState
    via the
    GlobalKey
    to trigger validation.
    dart
    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()) {
            // Save the form fields if necessary
            _formKey.currentState!.save();
            
            // Provide success feedback
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Processing Data')),
            );
          }
        },
        child: const Text('Submit'),
      ),
    )
  4. STOP AND ASK THE USER: Pause implementation and ask the user for the following context:
    • "What specific fields do you need in this form?"
    • "What are the exact validation rules for each field (e.g., regex patterns, minimum lengths)?"
    • "What action should occur upon successful validation (e.g., API payload submission, navigation)?"
  5. Validate-and-Fix Loop After generating the form, verify the following:
    • Ensure
      _formKey.currentState!.validate()
      is null-checked properly using the bang operator (
      !
      ) or safe calls if the key might be detached.
    • Verify that every
      validator
      function explicitly returns
      null
      on success. Returning an empty string (
      ""
      ) will trigger an error state with no text.
  1. 初始化有状态表单容器 创建一个
    StatefulWidget
    来承载表单。在
    State
    类中仅实例化一次
    GlobalKey<FormState>
    ,以避免在
    build
    周期中进行资源密集型的键重新生成操作。
    dart
    import 'package:flutter/material.dart';
    
    class CustomValidatedForm extends StatefulWidget {
      const CustomValidatedForm({super.key});
    
      
      State<CustomValidatedForm> createState() => _CustomValidatedFormState();
    }
    
    class _CustomValidatedFormState extends State<CustomValidatedForm> {
      // Instantiate the GlobalKey once in the State object
      final _formKey = GlobalKey<FormState>();
    
      
      Widget build(BuildContext context) {
        return Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              // Form fields will be injected here
            ],
          ),
        );
      }
    }
  2. 实现带验证逻辑的TextFormFields
    TextFormField
    组件注入到
    Form
    的组件树中。为每个字段提供
    validator
    函数。
    dart
    TextFormField(
      decoration: const InputDecoration(
        hintText: 'Enter your email',
        labelText: 'Email',
      ),
      validator: (String? value) {
        if (value == null || value.isEmpty) {
          return 'Please enter an email address';
        }
        if (!value.contains('@')) {
          return 'Please enter a valid email address';
        }
        // Return null if the input is valid
        return null; 
      },
      onSaved: (String? value) {
        // Handle save logic here
      },
    )
  3. 实现提交操作与验证触发 创建一个按钮,通过
    GlobalKey
    访问
    FormState
    以触发验证。
    dart
    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()) {
            // Save the form fields if necessary
            _formKey.currentState!.save();
            
            // Provide success feedback
            ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Processing Data')),
            );
          }
        },
        child: const Text('Submit'),
      ),
    )
  4. 暂停并询问用户: 暂停实现流程,并向用户询问以下上下文信息:
    • "此表单需要包含哪些具体字段?"
    • "每个字段的确切验证规则是什么(例如正则表达式、最小长度)?"
    • "验证成功后应执行什么操作(例如提交API请求、页面跳转)?"
  5. 验证与修复循环 生成表单后,验证以下内容:
    • 确保
      _formKey.currentState!.validate()
      使用感叹号运算符(
      !
      )进行了正确的空检查,或者在键可能未关联时使用安全调用。
    • 验证每个
      validator
      函数在验证通过时显式返回
      null
      。返回空字符串(
      ""
      )会触发无文本显示的错误状态。

Constraints

约束条件

  • DO NOT instantiate the
    GlobalKey<FormState>
    inside the
    build
    method. It must be a persistent member of the
    State
    class.
  • DO NOT use a
    StatelessWidget
    for the form container unless the
    GlobalKey
    is being passed down from a stateful parent.
  • DO NOT use standard
    TextField
    widgets if you require built-in form validation; you must use
    TextFormField
    (which wraps
    TextField
    in a
    FormField
    ).
  • ALWAYS return
    null
    from a
    validator
    function when the input is valid.
  • ALWAYS ensure the
    Form
    widget is a common ancestor to all
    TextFormField
    widgets that need to be validated together.
  • 请勿
    build
    方法中实例化
    GlobalKey<FormState>
    。它必须是
    State
    类的持久成员。
  • 请勿使用
    StatelessWidget
    作为表单容器,除非
    GlobalKey
    是从有状态的父组件传递下来的。
  • 如果需要内置表单验证,请勿使用标准的
    TextField
    组件;必须使用
    TextFormField
    (它在
    FormField
    中封装了
    TextField
    )。
  • 必须在输入有效时从
    validator
    函数返回
    null
  • 必须确保
    Form
    组件是所有需要一起验证的
    TextFormField
    组件的公共父组件。