如何解决Flutter GetX表单验证 可观察的onInit验证
我正在寻找一个示例,如何在GetX的最佳实践中处理表单和验证? 有什么好的例子吗?或者有人可以给我一个例子,说明我们如何做到最好?
解决方法
这里有一个示例,说明如何使用 GetX 的 observable 动态更新表单字段和提交按钮。
我不声称这是最佳做法。我相信有更好的方法来完成同样的事情。但是尝试使用 GetX 来执行验证很有趣。
表单 + 对象
根据 Observable 值变化重建的两个感兴趣的小部件:
- TextFormField
- InputDecoration 的
errorText
更改并将重建此小部件 -
onChanged: fx.usernameChanged
不会导致重建。这会在表单字段输入更改时调用控制器usernameChanged(String val)
中的函数。 - 它只是用新值更新
username
observable。 - 可以写成:
onChanged: (val) => fx.username.value = val
- InputDecoration 的
- RaisedButton(一个“提交”按钮)
-
onPressed
函数可以在null
和函数之间切换 -
null
禁用按钮(Flutter 中唯一的方法) - 这里的一个函数将启用按钮
-
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
FormX fx = Get.put(FormX()); // controller
return Scaffold(
appBar: AppBar(
title: Text('Form Validation'),),body: SafeArea(
child: Container(
alignment: Alignment.center,margin: 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(
() => RaisedButton(
child: Text('Submit'),onPressed: fx.submitFunc.value,// obs
),)
],);
}
}
GetX 控制器
解释/分解如下
class FormX extends GetxController {
RxString username = ''.obs;
RxString errorText = RxString(null);
Rx<Function> submitFunc = Rx<Function>(null);
@override
void onInit() {
super.onInit();
debounce(username,validations,time: 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(
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(Duration(seconds: 1),() => print('User account created'));
return true;
};
}
}
可观察的
从三个 observable 开始......
RxString username = ''.obs;
RxString errorText = RxString(null);
Rx<Function> submitFunc = Rx<Function>(null);
username
将保存最后输入到 TextFormField 中的任何内容。
errorText
使用 null
初始值实例化,因此用户名字段不是“无效”的开始。如果 not null(即使是空字符串),TextFormField 将呈现红色以表示无效输入。当字段中存在无效输入时,我们将显示错误消息。 (示例中的 min. 5 chars
:)
submitFunc
是一个持有提交按钮函数或 null
的 observable,因为 Dart 中的函数实际上是对象,这很好。 null
值初始分配将禁用按钮。
onInit
debounce
工作线程在更改 validations
可观察端 500 毫秒后调用 username
函数。
validations
将接收 username.value
作为其参数。
验证
在 validations
函数中,我们放置了我们想要运行的任何类型的验证:最小长度、坏字符、已取的名字、由于童年欺凌而导致我们个人不喜欢的名字等。
为了增加真实感,available()
函数为 async
。通常,这会查询数据库以检查用户名的可用性,因此在此示例中,在返回此验证检查之前有一个假的 1 秒延迟。
submitFunction()
返回一个函数,当我们对表单具有有效输入感到满意并允许用户继续时,该函数将替换 submitFunc
observable 中的空值。
更现实一点,我们可能会。期待提交按钮函数的一些返回值,所以我们可以让按钮函数返回一个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;
};
}
,
在这里看看
class LoginController extends GetxController{
TextEditingController email = TextEditingController();
TextEditingController password = TextEditingController();
void doLogin() {
if (email.text.isEmpty) {
errorSnackbar(msg: 'Enter Email Address');
} else if (password.text.isEmpty) {
errorSnackbar(msg: 'Enter Password');
} else if (password.text.length < 6) {
errorSnackbar(msg: "Password must be 6 digit");
} else {
// requestLogin();
}
}
void errorSnackbar({@required String msg}) {
return Get.snackbar(
'$msg',"Error !",snackPosition: SnackPosition.TOP,backgroundColor: Colors.red[200],colorText: Colors.white
);
}
}
,
GetX并不能解决所有问题,但是它具有一些实用程序方法可以帮助您实现所需的目标。例如,您可以将validator
和SnackBar
一起使用进行最终检查。这是一个代码段,可以帮助您了解基础知识。
TextFormField(
controller: emailController,autovalidateMode: AutovalidateMode.onUserInteraction,validator: (value) {
if (!GetUtils.isEmail(value))
return "Email is not valid";
else
return null;
},
GetUtils
几乎没有用于快速验证的便捷方法,您将不得不探索每种方法以查看其是否适合您的需求。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。