我正在寻找一个使用GetX处理表单和验证的最佳实践示例。是否有这样一个好的示例,或者可以有人向我展示如何最好地完成这项任务?
我正在寻找一个使用GetX处理表单和验证的最佳实践示例。是否有这样一个好的示例,或者可以有人向我展示如何最好地完成这项任务?
GetX并不是万能解决方案,但它有一些实用的方法可以帮助您实现想要的功能。例如,您可以与SnackBar
一起使用validator
进行最终检查。下面是一个代码片段,可能会帮助您了解基础知识。
TextFormField(
controller: emailController,
autovalidateMode: AutovalidateMode.onUserInteraction,
validator: (value) {
if (!GetUtils.isEmail(value))
return "Email is not valid";
else
return null;
},
),
GetUtils
有一些方便的方法可以快速进行验证,您需要探索每种方法以查看它是否适合您的需求。
class FormObxPage extends StatelessWidget {
const FormObxPage({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
FormX fx = Get.put(FormX()); // controller
return Scaffold(
appBar: AppBar(
title: const Text('Form Validation'),
),
body: SafeArea(
child: Container(
alignment: Alignment.center,
margin: const EdgeInsets.symmetric(horizontal: 5),
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
Obx(
() {
print('rebuild TextFormField ${fx.errorText.value}');
return TextFormField(
onChanged: fx.usernameChanged, // controller func
decoration: InputDecoration(
labelText: 'Username',
errorText: fx.errorText.value // obs
)
);
},
),
Obx(
() => ElevatedButton(
child: const Text('Submit'),
onPressed: fx.submitFunc.value, // obs
),
)
],
),
),
),
);
}
}
下面是解释/分解
class FormX extends GetxController {
RxString username = RxString('');
RxnString errorText = RxnString(null);
Rxn<Function()> submitFunc = Rxn<Function()>(null);
@override
void onInit() {
super.onInit();
debounce<String>(username, validations, time: const Duration(milliseconds: 500));
}
void validations(String val) async {
errorText.value = null; // reset validation errors to nothing
submitFunc.value = null; // disable submit while validating
if (val.isNotEmpty) {
if (lengthOK(val) && await available(val)) {
print('All validations passed, enable submit btn...');
submitFunc.value = submitFunction();
errorText.value = null;
}
}
}
bool lengthOK(String val, {int minLen = 5}) {
if (val.length < minLen) {
errorText.value = 'min. 5 chars';
return false;
}
return true;
}
Future<bool> available(String val) async {
print('Query availability of: $val');
await Future.delayed(
const Duration(seconds: 1),
() => print('Available query returned')
);
if (val == "Sylvester") {
errorText.value = 'Name Taken';
return false;
}
return true;
}
void usernameChanged(String val) {
username.value = val;
}
Future<bool> Function() submitFunction() {
return () async {
print('Make database call to create ${username.value} account');
await Future.delayed(const Duration(seconds: 1), () => print('User account created'));
return true;
};
}
}
从这三个可观察对象开始...
RxString username = RxString('');
RxnString errorText = RxnString(null);
Rxn<Function()> submitFunc = Rxn<Function()>(null);
username
将保存最后一次输入到TextFormField中的内容。
errorText
被实例化为null
的初始值,因此用户名字段一开始不是“无效”的。如果不是 null(即使是空字符串),TextFormField将以红色呈现,表示输入无效。当字段中有非有效输入时,我们将显示错误消息。(例如:最少5个字符
)
submitFunc
是一个可观察对象,用于保存提交按钮函数或null
值,因为在Dart中函数实际上是对象,所以这样做没问题。初始赋值为null
将禁用该按钮。
debounce
工作者会在username
可观察对象更改500毫秒后调用validations
函数。
validations
将接收username.value
作为其参数。
在validations
函数内,我们可以放置任何类型的验证:最小长度、不良字符、已使用名称、由于童年霸凌而不喜欢的名称等。
为了增加真实感,available()
函数是async
的。通常这将查询数据库以检查用户名是否可用,因此在此示例中,在返回此验证检查之前会有1秒的虚拟延迟。
submitFunction()
返回一个函数,该函数将替换submitFunc
可观察对象中的null值,当我们满意表单具有有效输入并允许用户继续时。
更现实一点,我们可能希望从提交按钮函数中返回一些返回值,因此我们可以使该按钮函数返回一个future bool:
Future<bool> Function() submitFunction() {
return () async {
print('Make database call to create ${username.value} account');
await Future.delayed(Duration(seconds: 1), () => print('User account created'));
return true;
};
}