Flutter表单验证通知插件validation_notifier的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter表单验证通知插件validation_notifier的使用

ValidationNotifier 是一个基于 ValueNotifier 的类,它允许你为输入值定义自定义验证规则,并在输入值发生变化时自动触发验证。下面我们将详细介绍如何使用 validation_notifier 插件进行表单验证,并提供一个完整的示例代码。

1. 创建验证规则

你可以通过继承 ValidationRule<T> 来创建自己的验证规则。每个规则需要实现两个方法:

  • errorMessage: 当验证失败时显示的错误信息。
  • checkIsValid: 检查输入值是否符合规则。

示例:创建必填字段规则

import 'package:validation_notifier/validation_notifier.dart';

class RequiredStringRule extends ValidationRule<String> {
  const RequiredStringRule();

  [@override](/user/override)
  String get errorMessage => '此字段是必填项';

  [@override](/user/override)
  bool checkIsValid(String? value) {
    return value?.isNotEmpty ?? false;
  }
}

示例:创建电子邮件格式规则

import 'package:validation_notifier/validation_notifier.dart';

class EmailFormatRule extends ValidationRule<String> {
  static final emailRegex = RegExp(
      r'^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$');

  const EmailFormatRule();

  [@override](/user/override)
  String get errorMessage => '无效的电子邮件格式';

  [@override](/user/override)
  bool checkIsValid(String? value) {
    if (value == null) {
      return false;
    } else {
      return emailRegex.hasMatch(value);
    }
  }
}

2. 添加验证规则

你可以将创建的规则添加到 ValidationNotifier<T> 中。ValidationNotifier<T> 会根据你定义的规则对输入值进行验证。

final email = ValidationNotifier<String>(rules: const [
  RequiredStringRule(),
  EmailFormatRule(),
]);

3. 使用 ValueListenableBuilder 构建表单

ValueListenableBuilder 可以监听 ValidationNotifier 的变化,并在输入值发生变化时更新 UI。我们可以使用它来构建 TextFormField,并在验证失败时显示错误信息。

ValueListenableBuilder<ValidationResult<String>>(
  valueListenable: email,
  builder: (context, value, child) {
    return TextFormField(
      onChanged: email.update,  // 当输入值发生变化时调用 update 方法
      keyboardType: TextInputType.emailAddress,
      autocorrect: false,
      decoration: InputDecoration(
        labelText: 'Email',
        errorText: value.errorMessage,  // 显示验证错误信息
      ),
    );
  },
)

4. 触发表单验证

你可以通过调用 ValidationNotifier<T>.validate() 方法来手动触发表单验证。通常情况下,我们会在用户点击提交按钮时进行验证。

void onLogin() {
  final emailResult = email.validate();
  final passwordResult = password.validate();

  if (emailResult.isValid && passwordResult.isValid) {
    // 验证成功,执行登录逻辑
    ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('所有字段都有效')));
  } else {
    // 验证失败,打印错误信息
    print('Email 错误: ${emailResult.errorMessage}');
    print('Password 错误: ${passwordResult.errorMessage}');
  }
}

5. 完整示例代码

下面是一个完整的示例代码,展示了如何使用 validation_notifier 插件来构建一个包含电子邮件和密码输入的登录表单。

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

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

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);

  final String title;

  [@override](/user/override)
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: LayoutBuilder(
        builder: (context, constraints) {
          return Center(
            child: Container(
              padding: const EdgeInsets.all(24),
              constraints: BoxConstraints(
                maxWidth: 512,
                maxHeight: constraints.maxHeight,
              ),
              child: const _LoginForm(),
            ),
          );
        },
      ),
    );
  }
}

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

  [@override](/user/override)
  _LoginFormState createState() => _LoginFormState();
}

class _LoginFormState extends State<_LoginForm> {
  final email = ValidationNotifier<String>(
    rules: const [
      RequiredStringRule(),
      EmailFormatRule(),
    ],
  );

  final password = ValidationNotifier<String>(
    rules: const [
      RequiredStringRule(),
      StringLengthRule(8),  // 密码长度至少为8个字符
    ],
  );

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.stretch,
      mainAxisSize: MainAxisSize.min,
      children: [
        ValueListenableBuilder<ValidationResult<String>>(
          valueListenable: email,
          builder: (context, value, child) {
            return TextFormField(
              onChanged: email.update,  // 当输入值发生变化时调用 update 方法
              keyboardType: TextInputType.emailAddress,
              autocorrect: false,
              decoration: InputDecoration(
                labelText: 'Email',
                errorText: value.errorMessage,  // 显示验证错误信息
              ),
            );
          },
        ),
        const SizedBox(height: 24),
        ValueListenableBuilder<ValidationResult<String>>(
          valueListenable: password,
          builder: (context, value, child) {
            return TextFormField(
              onChanged: password.update,  // 当输入值发生变化时调用 update 方法
              decoration: InputDecoration(
                labelText: 'Password',
                errorText: value.errorMessage,  // 显示验证错误信息
              ),
              obscureText: true,  // 隐藏密码输入
            );
          },
        ),
        const SizedBox(height: 24),
        ElevatedButton(
          onPressed: _onLogin,
          child: const Text('LOGIN'),
        )
      ],
    );
  }

  void _onLogin() {
    final emailResult = email.validate();
    final passwordResult = password.validate();

    if (emailResult.isValid && passwordResult.isValid) {
      // 验证成功,执行登录逻辑
      ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('所有字段都有效')));
    } else {
      // 验证失败,打印错误信息
      print('Email 错误: ${emailResult.errorMessage}');
      print('Password 错误: ${passwordResult.errorMessage}');
    }
  }
}

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

1 回复

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


当然,validation_notifier 是一个用于 Flutter 表单验证的插件,它提供了一种简洁且强大的方式来管理和通知表单字段的验证状态。下面是一个简单的示例,展示了如何使用 validation_notifier 来创建一个带有验证功能的表单。

首先,确保你已经在 pubspec.yaml 文件中添加了 validation_notifier 依赖:

dependencies:
  flutter:
    sdk: flutter
  validation_notifier: ^最新版本号  # 请替换为当前最新版本号

然后,运行 flutter pub get 来获取依赖。

接下来,我们编写一个示例代码,展示如何使用 validation_notifier

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:validation_notifier/validation_notifier.dart';

void main() {
  runApp(
    MultiProvider(
      providers: [
        ChangeNotifierProvider(create: (_) => FormNotifier()),
      ],
      child: MyApp(),
    ),
  );
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  final _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    final formNotifier = context.watch<FormNotifier>();

    return Scaffold(
      appBar: AppBar(
        title: Text('Form Validation with validation_notifier'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              TextFormField(
                decoration: InputDecoration(labelText: 'Email'),
                keyboardType: TextInputType.emailAddress,
                validator: (value) {
                  if (value == null || value.isEmpty || !value.contains('@')) {
                    formNotifier.setErrorFor('email', 'Invalid email address');
                    return null;
                  } else {
                    formNotifier.clearErrorFor('email');
                    return null;
                  }
                },
                onChanged: (value) {
                  formNotifier.setValueFor('email', value);
                },
              ),
              TextFormField(
                decoration: InputDecoration(labelText: 'Password'),
                obscureText: true,
                validator: (value) {
                  if (value == null || value.isEmpty || value.length < 6) {
                    formNotifier.setErrorFor('password', 'Password must be at least 6 characters long');
                    return null;
                  } else {
                    formNotifier.clearErrorFor('password');
                    return null;
                  }
                },
                onChanged: (value) {
                  formNotifier.setValueFor('password', value);
                },
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    // Perform form submission logic
                    print('Form is valid');
                  }
                },
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

class FormNotifier extends ValidationNotifier {
  // You can add more fields here if needed
  String? get email => values['email'];
  String? get password => values['password'];
}

在这个示例中,我们做了以下几件事:

  1. 依赖注入:使用 MultiProviderChangeNotifierProviderFormNotifier 注入到应用中。
  2. 创建表单:使用 FormTextFormField 创建了两个表单字段,分别是电子邮件和密码。
  3. 验证逻辑:在每个 TextFormFieldvalidator 属性中,根据字段值设置错误消息或清除错误消息,并通过 formNotifier.setErrorForformNotifier.clearErrorFor 方法更新验证状态。
  4. 值监听:在 onChanged 回调中,使用 formNotifier.setValueFor 方法更新字段值。
  5. 提交表单:在 ElevatedButtononPressed 回调中,调用 _formKey.currentState!.validate() 方法来验证表单。

请注意,虽然 validation_notifier 插件提供了更高级的功能来简化和优化表单验证流程,但在这个示例中,为了保持简单,我们手动处理了验证逻辑。在实际应用中,你可以根据 validation_notifier 的文档进一步利用其提供的特性来优化表单验证。

回到顶部