Flutter表单管理插件form_model的使用
Flutter表单管理插件form_model的使用
form_model 是一个强大的 Flutter 表单验证包。它提供了易于使用的表单验证功能,内置了多种验证器,并支持国际化。
功能
- 🚀 简易的表单验证
- 🎯 单一责任验证器,代码清晰可维护
- 🌐 内置国际化支持,包含备用语言
- 🧩 可扩展性,可以添加自定义验证器和翻译
- 🔄 不可变状态管理
- 🔗 无缝集成到 Flutter 小部件中
- 🧩 支持高级表单控件(如日期选择器、多选等)
- 🧬 与状态管理解决方案(如 BLoC)配合良好
- 🧪 全面的测试覆盖率
截图
以下是一些 form_model 的运行截图:
安装
在你的 pubspec.yaml 文件中添加 form_model:
dependencies:
form_model: ^1.0.2+2
然后运行:
flutter pub get
基本用法
以下是一个简单的 form_model 使用示例:
import 'package:form_model/form_model.dart';
// 创建一个用于电子邮件字段的 FormModel
final emailModel = FormModel<String>(
validators: [RequiredValidator(), EmailValidator()],
);
// 设置值并验证
final validatedModel = emailModel.setValue('user@example.com').validate();
if (validatedModel.isValid) {
print('Email is valid: ${validatedModel.value}');
} else {
print('Validation error: ${validatedModel.error?.translatedMessage}');
}
注意:每个验证器负责检查输入的一个特定方面,并且只返回一种类型的错误。遵循这一原则可以帮助你创建适用于应用的自定义验证器。
高级用法
对于更复杂的表单,你可以组合多个 FormModel 实例。以下是一个带有密码确认字段的示例:
class RegistrationForm {
final FormModel<String> username;
final FormModel<String> email;
final FormModel<String> password;
late final FormModel<String> confirmPassword;
RegistrationForm({
required this.username,
required this.email,
required this.password,
}) {
confirmPassword = FormModel<String>(
validators: [
RequiredValidator(),
StringConfirmPasswordMatchValidator(matchingValue: password.value),
],
);
}
bool get isValid =>
username.isValid &&
email.isValid &&
password.isValid &&
confirmPassword.isValid;
void validate() {
username.validate();
email.validate();
password.validate();
confirmPassword = confirmPassword
.replaceValidator(
predicate: (validator) => validator is StringConfirmPasswordMatchValidator,
newValidator: StringConfirmPasswordMatchValidator(matchingValue: password.value),
)
.validate();
}
void updatePassword(String newPassword) {
password.setValue(newPassword);
// 更新确认密码验证器
confirmPassword = confirmPassword
.replaceValidator(
predicate: (validator) => validator is StringConfirmPasswordMatchValidator,
newValidator: StringConfirmPasswordMatchValidator(matchingValue: newPassword),
);
}
}
此示例展示了如何正确设置和更新密码匹配验证器。
验证器
form_model 包含多种内置验证器,每个验证器负责单个方面的验证:
RequiredValidatorEmailValidatorStringMinLengthValidatorStringMaxLengthValidatorPasswordLengthValidatorPasswordUppercaseValidatorPasswordLowercaseValidatorPasswordNumberValidatorPasswordSpecialCharValidatorDateTimeValidatorStringDateTimeAgeMinValidatorStringDateTimeAgeMaxValidatorStringPhoneNumberValidatorStringNumbersOnlyValidatorStringTextOnlyValidatorStringUrlValidatorStringWordsCountMinValidatorStringWordsCountMaxValidatorStringCreditCardValidatorCustomEqualValidatorStringCustomPatternValidatorIpAddressValidatorIpv6AddressValidatorStringNumMinValidatorStringNumMaxValidatorStringContainsValidatorStringNotContainsValidatorFileTypeValidatorFileSizeValidatorBoolTrueValidatorBoolFalseValidatorBoolAgreeToTermsAndConditionsValidator
每个验证器专注于单一的验证规则,符合单一职责原则。
国际化
form_model 支持多种语言:
// 设置当前语言环境
FormModelLocalizations().setCurrentLocale(const Locale('es'));
// 获取翻译后的错误消息
final errorMessage = emailModel.error?.translatedMessage;
支持的语言
form_model 支持以下语言:
- 英语 (en)
- 西班牙语 (es)
- 法语 (fr)
- 德语 (de)
- 阿拉伯语 (ar)
- 中文(简体) (zh_CN)
- 印地语 (hi)
- 意大利语 (it)
- 日语 (ja)
- 韩语 (ko)
- 荷兰语 (nl)
- 葡萄牙语 (pt)
- 俄语 (ru)
- 土耳其语 (tr)
- 乌克兰语 (uk)
- 越南语 (vi)
- 波兰语 (pl)
- 瑞典语 (sv)
与 BLoC 和 Freezed 集成
form_model 可以无缝集成到 BLoC 模式中。以下是一个使用 Freezed 的 Flutter BLoC 状态示例:
@freezed
class RegistrationState with _$RegistrationState {
const factory RegistrationState({
@Default(FormModel<String>(validators: [RequiredValidator()]))
FormModel<String> username,
@Default(FormModel<String>(validators: [RequiredValidator(), EmailValidator()]))
FormModel<String> email,
@Default(FormModel<String>(validators: [
RequiredValidator(),
PasswordLengthValidator(minLength: 8),
PasswordUppercaseValidator(),
PasswordLowercaseValidator(),
PasswordNumberValidator(),
PasswordSpecialCharValidator(),
]))
FormModel<String> password,
@Default(false) bool isSubmitting,
@Default(false) bool isSuccess,
String? errorMessage,
}) = _RegistrationState;
}
自定义验证器
自定义验证器允许你创建未被内置验证器覆盖的特定验证规则。以下是一个简单的自定义验证器示例,该验证器检查字符串是否以特定前缀开头:
String? validatePrefix(String? value) {
const requiredPrefix = 'USER_';
if (value == null || !value.startsWith(requiredPrefix)) {
return 'Value must start with $requiredPrefix';
}
return null;
}
final userIdModel = FormModel<String>(
validators: [
RequiredValidator(),
CustomValidator(validator: validatePrefix),
],
);
// 使用示例
void validateUserId(String userId) {
final validatedModel = userIdModel.setValue(userId).validate();
if (validatedModel.isValid) {
print('Valid User ID: ${validatedModel.value}');
} else {
print('Invalid User ID: ${validatedModel.error?.translatedMessage}');
}
}
// 示例
validateUserId('USER_123'); // 有效
validateUserId('ADMIN_456'); // 无效
此自定义验证器检查输入字符串是否以前缀 'USER_' 开头。它演示了如何轻松创建应用程序特定的验证逻辑。自定义验证函数应返回一个包含错误消息的字符串(如果验证失败),或者返回 null(如果验证通过)。这种方法允许你扩展 form_model 的能力以满足特定需求,同时保持代码的整洁和模块化。
处理自定义对象
form_model 还可以处理复杂的自定义对象。以下是一个使用 Address 类的示例:
class Address {
final String street;
final String city;
Address({required this.street, required this.city});
}
String? validateStreet(Address? value) {
if (value == null || value.street.isEmpty) return 'Street is required';
return null;
}
String? validateCity(Address? value) {
if (value == null || value.city.isEmpty) return 'City is required';
return null;
}
final addressModel = FormModel<Address>(
validators: [
CustomValidator(validator: validateStreet),
CustomValidator(validator: validateCity),
],
);
// 使用示例
void updateAddress(String street, String city) {
final newAddress = Address(street: street, city: city);
addressModel.setValue(newAddress).validate();
}
这种方法允许你在保持单独验证规则分离的同时验证复杂对象。
自定义翻译
你可以为自定义和预定义错误消息设置自定义翻译:
void setCustomTranslations() {
// 为自定义错误设置自定义翻译
FormModelLocalizations().setCustomErrorTranslations(
'en',
const CustomFormErrorKey('password_no_exclamation'),
'Password must contain an exclamation mark',
);
// 覆盖预定义错误的翻译
FormModelLocalizations().setCustomErrorTranslations(
'en',
const PredefinedFormErrorKey(PredefinedFormErrorType.required),
'This field cannot be left empty',
);
// 为其他语言设置翻译
FormModelLocalizations().setCustomErrorTranslations(
'es',
const CustomFormErrorKey('password_no_exclamation'),
'La contraseña debe contener un signo de exclamación',
);
FormModelLocalizations().setCustomErrorTranslations(
'es',
const PredefinedFormErrorKey(PredefinedFormErrorType.required),
'Este campo no puede estar vacío',
);
}
更多关于Flutter表单管理插件form_model的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter表单管理插件form_model的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何在Flutter中使用form_model插件来管理表单的示例代码。form_model插件提供了一种声明式的方式来处理表单状态,使得表单验证和管理变得更加简单。
首先,确保你已经在pubspec.yaml文件中添加了form_model依赖:
dependencies:
flutter:
sdk: flutter
form_model: ^x.y.z # 请替换为最新版本号
然后运行flutter pub get来获取依赖。
接下来,我们将创建一个简单的表单,包含用户名和密码字段,并使用form_model来管理这些字段的状态和验证。
import 'package:flutter/material.dart';
import 'package:form_model/form_model.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Form Model Example'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: MyForm(),
),
),
);
}
}
class MyForm extends StatelessWidget {
@override
Widget build(BuildContext context) {
return FormModel(
model: MyFormModel(),
builder: (context, formModel, child) {
return Column(
children: [
TextFormFieldModel(
formModel: formModel,
attributeName: 'username',
decoration: InputDecoration(labelText: 'Username'),
validators: [
Validators.required('Username is required'),
Validators.minLength(3, 'Username must be at least 3 characters long'),
],
),
TextFormFieldModel(
formModel: formModel,
attributeName: 'password',
decoration: InputDecoration(labelText: 'Password'),
obscureText: true,
validators: [
Validators.required('Password is required'),
Validators.minLength(6, 'Password must be at least 6 characters long'),
],
),
SizedBox(height: 16),
ElevatedButton(
onPressed: formModel.isValid ? () => formModel.submit() : null,
child: Text('Submit'),
),
if (formModel.isSubmitting)
CircularProgressIndicator(),
if (formModel.hasError)
Text(formModel.error ?? ''),
],
);
},
);
}
}
class MyFormModel extends FormModel {
String? username;
String? password;
@override
void initialize() {
addAttribute('username', String, [null]);
addAttribute('password', String, [null]);
}
@override
Future<void> submit() async {
setState(() {
isSubmitting = true;
error = null;
});
try {
// 模拟异步提交操作,例如发送到服务器
await Future.delayed(Duration(seconds: 2));
print('Form submitted successfully!');
// 根据实际情况处理提交结果
} catch (e) {
setState(() {
error = 'Submission failed: $e';
});
} finally {
setState(() {
isSubmitting = false;
});
}
}
}
在这个示例中,我们做了以下几件事情:
-
定义表单模型:
MyFormModel继承自FormModel,并定义了username和password属性。在initialize方法中,我们通过addAttribute方法注册这些属性。 -
创建表单视图:
MyForm是一个无状态组件,它使用FormModel组件来包装表单,并通过TextFormFieldModel组件来创建具体的输入字段。TextFormFieldModel组件通过attributeName属性与表单模型中的属性关联。 -
添加验证规则:在
TextFormFieldModel组件中,我们使用了validators属性来定义验证规则。这里使用了Validators.required和Validators.minLength来验证输入。 -
提交表单:在
ElevatedButton的onPressed回调中,我们检查表单是否有效(formModel.isValid),如果有效则调用formModel.submit方法来提交表单。 -
处理提交结果:在
MyFormModel的submit方法中,我们模拟了一个异步提交操作,并在提交完成后更新表单的状态。
这个示例展示了如何使用form_model插件来管理一个简单的Flutter表单,包括输入字段、验证和提交逻辑。你可以根据需要扩展和修改这个示例以适应你的具体需求。

