Flutter表单验证插件ready_validation的使用

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

Flutter表单验证插件ready_validation的使用

如何使用

如果你在使用本地化,必须在你的MaterialApp中添加localizationDelegate

return MaterialApp(
  localizationsDelegates: [
    ReadyValidationMessages.delegate,
    ...其他委托
  ],
  home: MyApplicationHome(),
);

如果你想在整个应用中使用指定的消息,可以这样做

ValidationMessagesConfig(
  messages: ReadyValidationMessagesAr(),
  child: // 屏幕或MaterialApp
);

不用担心,每个验证都有一个自定义消息的参数。

使用方法

/// 非常简单

TextFormField(
  validator: context
    .string()
    .required()
    .notEmpty()
    .hasMaxLength(10)
    .hasMinLength(15)
    .isNumber()
    .greaterThan(10),
);

解释

  1. 它获取String?值的验证器。
  2. 它检查值是否不为null,并将验证器转换为String而不是String?

    此时我们可以使用非空字符串验证。

  3. 检查字符串是否为空。
  4. 检查字符串的最大长度。
  5. 检查字符串的最小长度。
  6. 检查字符串是否为数字,并且如果通过则将验证器转换为num验证器。

    此时我们可以使用所有数字验证,如greaterThan

  7. 检查转换后的数字是否大于10。
  8. 如果任何验证失败,它将返回其验证消息,并不会继续进行后续验证。

非上下文验证

BuildContext用于应用本地化和全局配置的本地化,但有时你需要检查是否有效。这同样得到了支持,这次你不需要验证是否需要,因为值已经是非空的。

var number = "7";

var isValid = number
    .validateWith((v) => v.isNumber())
    .validateWith((v) => v.isBetween(5, 10))
    .isValid();

/// 或者
isValid = number.validateWith((v) => v.isNumber().isBetween(5, 10)).isValid();

// 忽略:避免打印
print(isValid);

可用验证

所有类型

  • required notEqual equal isIn isNotIn validateWith

字符串

  • isEmail isCreditCard startsWith contains endsWith notEmpty notEmptyOrWhiteSpace matches hasLength hasMinLength
  • hasMaxLength hasRange isAngelCompany isAngelJob isCrunchbaseOrganization isCrunchbasePerson isFacebookUrl isGitHubUrl
  • isGooglePlusUrl isHackerNewsUserUrl isHackerNewsItemUrl isInstagramUrl isLinkedInProfile isLinkedInCompany isLinkedInPost
  • isRedditUrl isSnapchatUrl isStackexchangeUrl isStackoverflowQuestionUrl isStackoverflowUserUrl isTelegramProfileUrl isMediumPostUrl
  • isMediumUserUrl isTwitterStatusUrl isTwitterUserUrl isYoutubeChannelUrl isYoutubeVideoUrl isYoutubeUserUrl

数字

  • lessThan greaterThan isBetween lessThanOrEqual greaterThanOrEqual isBetweenOrEqual isDivisibleBy
  • isNegative isPositive isEven isOdd

日期

  • isAfter isAfterOrEqual isBefore isBeforeOrEqual isBetween isBetweenOrEqual

注意:大多数验证器都有带有前缀Fn的替代品,例如startsWithFn,它接受函数而不是值。

验证器

/// 字符串验证器
context.string();

/// 数字验证器
context.number();

/// 整数验证器
context.integer();

/// 小数验证器
context.decimal(); // 对于双精度浮点数

/// 布尔验证器
context.boolean();

/// 日期时间验证器
context.dateTime();

/// 时间选择器验证器(即将添加)
context.timeOfDay();

/// 列表验证器
context.list<T>(); 

/// 映射验证器
context.map<K,V>(); 

/// 其他验证器
context.validator<T>(); 

转换

在任何步骤中,你可以将验证器转换为另一种类型,它仍然可以在字段中使用。

假设我们创建了一个验证器,用于我们的TextFormField,它接受一个字符串类型的验证器。

因此,我们的验证器将是:

context.string();

现在我们需要将其转换为数字验证器。

context
  .string()
  .required() // 确保它不为null
  .transform((v) => int.parse(v))

现在你可以使用任何数字验证,如greaterThan,但你不能使用hasMaxLength,因为它对于字符串而言,直到你再次将其转换为字符串验证器。

条件验证

context
  .string()
  .required()
  .hasMaxLength(10)
  .hasMinLength(15)
  .when((x) => false) /// 在这一点上`hasMinLength`被忽略
  .isNumber()
  .greaterThan(10),
/// 所以验证顺序将是
/// `required` => `hasMaxLength` => `isNumber` => `greaterThan`

高级

有时候你想要使用自己的消息,那么你必须创建自己的委托和类。

默认委托看起来像这样:

class _ReadyValidationMessagesDelegate
    extends LocalizationsDelegate<ReadyValidationMessages> {
  const _ReadyValidationMessagesDelegate();

  [@override](/user/override)
  Future<ReadyValidationMessages> load(Locale locale) {
    return SynchronousFuture<ReadyValidationMessages>(
        lookupReadyValidationMessages(locale));
  }

  [@override](/user/override)
  bool isSupported(Locale locale) =>
      <String>['ar', 'en', 'fr', 'ur'].contains(locale.languageCode);

  [@override](/user/override)
  bool shouldReload(_ReadyValidationMessagesDelegate old) => false;
}

ReadyValidationMessages lookupReadyValidationMessages(Locale locale) {
  // 当仅指定了语言代码时的查找逻辑。
  switch (locale.languageCode) {
    case 'ar':
      return ReadyValidationMessagesAr();
    case 'en':
      return ReadyValidationMessagesEn();
    case 'fr':
      return ReadyValidationMessagesFr();
    case 'ur':
      return ReadyValidationMessagesUr();
  }

  throw FlutterError(
      'ReadyValidationMessages.delegate failed to load unsupported locale "$locale". This is likely '
      'an issue with the localizations generation tool. Please file an issue '
      'on GitHub with a reproducible sample app and the gen-l10n configuration '
      'that was used.');
}

你也需要创建你自己的ReadyValidationMessages类。

现在,不要使用我们的委托,而是使用你自己的。

return MaterialApp(
  localizationsDelegates: [
    CustomReadyValidationMessages(),
    ...其他委托
  ],
  home: MyApplicationHome(),
);

注入

如果你需要制作自己的验证器,它可以与其他验证器一起使用,比如这样:

TextFormField(
  validator: context
    .string()
    .required()
    .myCustomValidation() /// 这是你自定义的验证
    .hasMaxLength(10)
    .hasMinLength(15)
    .isNumber()
    .greaterThan(10),
);

为此,你必须扩展字段验证器。

extension MyCustomValidationExtension<T> on FieldValidator<T, String> {
  FieldValidator<T, String> myCustomValidation() {
    return next(
      (messages, value) => !validate(value) /// 在这里验证文本
          ? "My custom message"
          : null,
    );
  }
}

/// FieldValidator 接受两个泛型参数
/// 第一个是调用者,意味着传递给验证器的值的类型是什么
/// 因为我们需要验证器与字符串值一起工作,并且任何转换为字符串的类型,我们将使用T作为第一个参数

完整示例Demo

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

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

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

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

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

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Ready Validation Demo'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: [
              TextFormField(
                decoration: InputDecoration(labelText: 'Enter Number'),
                validator: context
                  .string()
                  .required()
                  .isNumber()
                  .greaterThan(0),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  if (_formKey.currentState!.validate()) {
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(content: Text('Form is valid!')),
                    );
                  } else {
                    ScaffoldMessenger.of(context).showSnackBar(
                      SnackBar(content: Text('Form is invalid!')),
                    );
                  }
                },
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

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

1 回复

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


当然,下面是一个关于如何使用 ready_validation 插件进行 Flutter 表单验证的示例代码。ready_validation 是一个用于 Flutter 的表单验证库,可以简化表单字段的验证过程。

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

dependencies:
  flutter:
    sdk: flutter
  ready_validation: ^x.y.z  # 请替换为最新版本号

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

接下来是一个完整的示例代码,展示了如何使用 ready_validation 进行表单验证:

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

void main() {
  runApp(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 StatefulWidget {
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final _formKey = GlobalKey<FormState>();
  final _emailController = TextEditingController();
  final _passwordController = TextEditingController();
  late ReadyValidation _readyValidation;

  @override
  void initState() {
    super.initState();
    _readyValidation = ReadyValidation()
      ..addValidator('email', _emailController, [
        RequiredValidator(errorText: 'Email is required'),
        EmailValidator(errorText: 'Email is not valid'),
      ])
      ..addValidator('password', _passwordController, [
        RequiredValidator(errorText: 'Password is required'),
        MinLengthValidator(6, errorText: 'Password must be at least 6 characters long'),
      ]);
  }

  @override
  void dispose() {
    _emailController.dispose();
    _passwordController.dispose();
    super.dispose();
  }

  void _submitForm() {
    if (_formKey.currentState!.validate()) {
      if (_readyValidation.validate()) {
        // 表单验证通过,执行提交逻辑
        print('Form submitted successfully');
      } else {
        // 使用ready_validation验证失败,显示错误信息
        _readyValidation.showErrors(context);
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Form Validation Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Form(
          key: _formKey,
          child: Column(
            children: <Widget>[
              TextFormField(
                controller: _emailController,
                decoration: InputDecoration(labelText: 'Email'),
                validator: (value) {
                  // 这里的validator可以留空,因为ready_validation会处理
                  return null;
                },
              ),
              TextFormField(
                controller: _passwordController,
                decoration: InputDecoration(labelText: 'Password'),
                obscureText: true,
                validator: (value) {
                  // 这里的validator可以留空,因为ready_validation会处理
                  return null;
                },
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: _submitForm,
                child: Text('Submit'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

在这个示例中:

  1. 我们在 initState 方法中初始化了 ReadyValidation 对象,并为 emailpassword 字段添加了相应的验证规则。
  2. TextFormFieldvalidator 属性留空,因为我们使用 ready_validation 来处理验证逻辑。
  3. _submitForm 方法中,首先使用 Flutter 自带的 FormState.validate 方法进行初步验证(通常用于非空验证),然后使用 ReadyValidation.validate 方法进行更复杂的验证。
  4. 如果 ReadyValidation.validate 返回 false,则调用 ReadyValidation.showErrors 方法显示错误信息。

这个示例展示了如何使用 ready_validation 插件进行表单验证,同时结合了 Flutter 自带的表单验证机制。

回到顶部