Flutter表单验证插件formality的使用

Flutter表单验证插件formality的使用

Formality 是一个用于 Flutter 的简单表单验证库。它可以帮助开发者轻松实现表单字段的验证,并且支持动画效果来提示用户输入错误。

示例

以下是一个完整的示例,展示了如何使用 Formality 来创建一个带有验证功能的表单。

完整代码

import 'package:flutter/material.dart';
import 'package:formality/formality.dart';

void main() {
  runApp(const MyApp());
}

// 定义表单数据模型
class ExampleFormModel {
  final String firstName;
  final String lastName;
  final String email;

  ExampleFormModel({
    this.firstName = '',
    this.lastName = '',
    this.email = '',
  });

  ExampleFormModel copyWith({
    String? firstName,
    String? lastName,
    String? email,
  }) {
    return ExampleFormModel(
      firstName: firstName ?? this.firstName,
      lastName: lastName ?? this.lastName,
      email: email ?? this.email,
    );
  }
}

// 定义正则表达式用于验证
final nameRegex = RegExp(r"[a-zA-Z0-9 \.´'‘’]");
final emailRegex = RegExp(
  r"[a-zA-Z0-9.a-zA-Z0-9.!#$%&'*+-/=?^_`{|}~]+@[a-zA-Z0-9]+\.[a-zA-Z]+",
);

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const ExampleFormPage(),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Formality')),
      body: FormBuilder(
        initialFormData: ExampleFormModel(firstName: 'John'),
        builder: (context, formData, controller) {
          final ExampleFormModel(:firstName, :lastName, :email) = formData;

          return Center(
            child: FractionallySizedBox(
              widthFactor: 0.7,
              child: Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  // 验证名字字段
                  Validation(
                    valid: nameRegex.hasMatch(firstName) && firstName.isNotEmpty,
                    error: const Text(
                      'Invalid first name',
                      style: TextStyle(color: Colors.red),
                    ),
                    child: TextFormField(
                      initialValue: firstName,
                      decoration: const InputDecoration(
                        labelText: 'First name',
                      ),
                      onChanged: (value) {
                        controller.setForm(
                          formData.copyWith(firstName: value),
                        );
                      },
                    ),
                  ),
                  // 验证姓氏字段
                  Validation(
                    valid: nameRegex.hasMatch(lastName) && lastName.isNotEmpty,
                    error: const Text(
                      'Invalid last name',
                      style: TextStyle(color: Colors.red),
                    ),
                    child: TextFormField(
                      initialValue: lastName,
                      decoration: const InputDecoration(
                        labelText: 'Last name',
                      ),
                      onChanged: (value) {
                        controller.setForm(
                          formData.copyWith(lastName: value),
                        );
                      },
                    ),
                  ),
                  // 验证邮箱字段
                  Validation(
                    valid: emailRegex.hasMatch(email),
                    error: const Text(
                      'Invalid email',
                      style: TextStyle(color: Colors.red),
                    ),
                    child: TextFormField(
                      initialValue: email,
                      decoration: const InputDecoration(
                        labelText: 'Email',
                      ),
                      onChanged: (value) {
                        controller.setForm(
                          formData.copyWith(email: value),
                        );
                      },
                    ),
                  ),
                  // 提交按钮
                  Padding(
                    padding: const EdgeInsets.only(top: 20),
                    child: ElevatedButton(
                      onPressed: () {
                        if (controller.validate()) {
                          ScaffoldMessenger.of(context).showSnackBar(
                            const SnackBar(
                              content: Text('Submitted!'),
                              backgroundColor: Colors.green,
                            ),
                          );
                        } else {
                          ScaffoldMessenger.of(context).showSnackBar(
                            const SnackBar(
                              content: Text('Error!'),
                              backgroundColor: Colors.redAccent,
                            ),
                          );
                        }
                      },
                      child: const Text('Submit'),
                    ),
                  ),
                ],
              ),
            ),
          );
        },
      ),
    );
  }
}

运行效果

运行上述代码后,您将看到一个简单的表单,包含三个字段:名字、姓氏和邮箱。每个字段都有验证规则:

  • 名字和姓氏必须符合正则表达式 [a-zA-Z0-9 \.´'‘’]
  • 邮箱必须符合标准的电子邮件格式。

当用户提交表单时,如果验证失败,会弹出红色错误提示;如果验证通过,则会显示绿色成功提示。

动画效果

所有验证错误提示都带有动画效果,如图所示:

Basic demo gif

自定义动画

如果您想自定义字段的动画效果,可以使用 Validation.childAnimationBuilderValidation.errorAnimationBuilder

例如:

Validation(
  valid: emailRegex.hasMatch(email),
  error: const Text(
    'Invalid email',
    style: TextStyle(color: Colors.red),
  ),
  childAnimationBuilder: (context, child) => ScaleTransition(
    scale: AlwaysStoppedAnimation(0.8),
    child: child,
  ),
  errorAnimationBuilder: (context, child) => SlideTransition(
    position: Tween<Offset>(
      begin: const Offset(0, -1),
      end: Offset.zero,
    ).animate(
      CurvedAnimation(
        parent: AnimationController(
          vsync: context,
          duration: const Duration(milliseconds: 500),
        ),
        curve: Curves.easeInOut,
      ),
    ),
    child: child,
  ),
  child: TextFormField(
    initialValue: email,
    decoration: const InputDecoration(
      labelText: 'Email',
    ),
    onChanged: (value) {
      controller.setForm(
        formData.copyWith(email: value),
      );
    },
  ),
),

更多关于Flutter表单验证插件formality的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter表单验证插件formality的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


formality 是一个用于 Flutter 表单验证的插件,它提供了一种简洁且类型安全的方式来处理表单验证。通过 formality,你可以轻松地定义表单的验证规则,并在表单提交时自动验证所有字段。

下面是一个简单的示例,演示如何使用 formality 进行表单验证。

1. 添加依赖

首先,在你的 pubspec.yaml 文件中添加 formality 依赖:

dependencies:
  flutter:
    sdk: flutter
  formality: ^0.1.0

然后运行 flutter pub get 来安装依赖。

2. 创建表单模型

接下来,创建一个表单模型类,用于定义表单的字段和验证规则。

import 'package:formality/formality.dart';

class LoginForm with FormMixin {
  final username = FormField<String>(rules: [RequiredRule()]);
  final password = FormField<String>(rules: [RequiredRule(), MinLengthRule(6)]);

  [@override](/user/override)
  List<FormField> get fields => [username, password];
}

在这个例子中,LoginForm 类包含了两个字段:usernamepassword。每个字段都定义了一些验证规则,例如 RequiredRule 表示该字段是必填的,MinLengthRule 表示密码至少需要 6 个字符。

3. 构建表单界面

接下来,使用 Formality 构建表单界面。

import 'package:flutter/material.dart';
import 'package:formality/formality.dart';

class LoginScreen extends StatefulWidget {
  [@override](/user/override)
  _LoginScreenState createState() => _LoginScreenState();
}

class _LoginScreenState extends State<LoginScreen> {
  final _form = LoginForm();

  void _submit() {
    if (_form.validate()) {
      // 表单验证通过,处理提交逻辑
      print('Form is valid');
      print('Username: ${_form.username.value}');
      print('Password: ${_form.password.value}');
    } else {
      // 表单验证失败
      print('Form is invalid');
    }
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Login'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          children: [
            TextFormField(
              decoration: InputDecoration(labelText: 'Username'),
              onChanged: (value) => _form.username.value = value,
              validator: (value) => _form.username.errorText,
            ),
            TextFormField(
              decoration: InputDecoration(labelText: 'Password'),
              obscureText: true,
              onChanged: (value) => _form.password.value = value,
              validator: (value) => _form.password.errorText,
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: _submit,
              child: Text('Submit'),
            ),
          ],
        ),
      ),
    );
  }
}

在这个例子中,LoginScreen 是一个包含两个 TextFormField 的表单界面。onChanged 回调用于更新表单模型中的字段值,validator 用于显示字段的验证错误信息。

4. 运行应用

现在你可以运行应用并测试表单验证功能。如果用户输入了无效的值,相应的错误信息将会显示在表单字段下方。

5. 自定义验证规则

formality 允许你自定义验证规则。例如,你可以创建一个自定义的验证规则来验证电子邮件格式:

class EmailRule extends FormRule<String> {
  [@override](/user/override)
  String? validate(String? value) {
    if (value == null || value.isEmpty) {
      return 'Email is required';
    }
    if (!RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(value)) {
      return 'Invalid email format';
    }
    return null;
  }
}

然后在表单模型中使用这个规则:

class LoginForm with FormMixin {
  final email = FormField<String>(rules: [EmailRule()]);
  final password = FormField<String>(rules: [RequiredRule(), MinLengthRule(6)]);

  [@override](/user/override)
  List<FormField> get fields => [email, password];
}
回到顶部