Flutter表单管理插件form_model的使用
Flutter表单管理插件form_model的使用
form_model
是一个强大的 Flutter 表单验证包。它提供了易于使用的表单验证功能,内置了多种验证器,并支持国际化。
功能
- 🚀 简易的表单验证
- 🎯 单一责任验证器,代码清晰可维护
- 🌐 内置国际化支持,包含备用语言
- 🧩 可扩展性,可以添加自定义验证器和翻译
- 🔄 不可变状态管理
- 🔗 无缝集成到 Flutter 小部件中
- 🧩 支持高级表单控件(如日期选择器、多选等)
- 🧬 与状态管理解决方案(如 BLoC)配合良好
- 🧪 全面的测试覆盖率
截图
以下是一些 form_model
的运行截图:
![Screenshot 1](https://raw.githubusercontent.com/sukhrob-djumaev/form_model/main/screenshots/1.png)
![Screenshot 2](https://raw.githubusercontent.com/sukhrob-djumaev/form_model/main/screenshots/2.png)
![Screenshot 3](https://raw.githubusercontent.com/sukhrob-djumaev/form_model/main/screenshots/3.png)
![Screenshot 4](https://raw.githubusercontent.com/sukhrob-djumaev/form_model/main/screenshots/4.png)
![Screenshot 5](https://raw.githubusercontent.com/sukhrob-djumaev/form_model/main/screenshots/5.png)
![Screenshot 6](https://raw.githubusercontent.com/sukhrob-djumaev/form_model/main/screenshots/6.png)
![Screenshot 7](https://raw.githubusercontent.com/sukhrob-djumaev/form_model/main/screenshots/7.png)
安装
在你的 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
包含多种内置验证器,每个验证器负责单个方面的验证:
RequiredValidator
EmailValidator
StringMinLengthValidator
StringMaxLengthValidator
PasswordLengthValidator
PasswordUppercaseValidator
PasswordLowercaseValidator
PasswordNumberValidator
PasswordSpecialCharValidator
DateTimeValidator
StringDateTimeAgeMinValidator
StringDateTimeAgeMaxValidator
StringPhoneNumberValidator
StringNumbersOnlyValidator
StringTextOnlyValidator
StringUrlValidator
StringWordsCountMinValidator
StringWordsCountMaxValidator
StringCreditCardValidator
CustomEqualValidator
StringCustomPatternValidator
IpAddressValidator
Ipv6AddressValidator
StringNumMinValidator
StringNumMaxValidator
StringContainsValidator
StringNotContainsValidator
FileTypeValidator
FileSizeValidator
BoolTrueValidator
BoolFalseValidator
BoolAgreeToTermsAndConditionsValidator
每个验证器专注于单一的验证规则,符合单一职责原则。
国际化
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表单,包括输入字段、验证和提交逻辑。你可以根据需要扩展和修改这个示例以适应你的具体需求。