Flutter GetX表单验证

时间:2020-10-26 20:31:33

标签: forms flutter validation getx

我正在寻找一个示例,如何在GetX的最佳实践中处理表单和验证? 有什么好的例子吗?或者有人可以给我一个例子,说明我们如何做到最好?

3 个答案:

答案 0 :(得分:4)

这里有一个示例,说明如何使用 GetX 的 observable 动态更新表单字段和提交按钮。

我不声称这是最佳做法。我相信有更好的方法来完成同样的事情。但是尝试使用 GetX 来执行验证很有趣。

表单 + 对象

根据 Observable 值变化重建的两个感兴趣的小部件:

  1. TextFormField
    • InputDecoration 的 errorText 更改并将重建此小部件
    • onChanged: fx.usernameChanged 不会导致重建。这会在表单字段输入更改时调用控制器 usernameChanged(String val) 中的函数。
    • 它只是用新值更新 username observable。
    • 可以写成:
    • onChanged: (val) => fx.username.value = val
  2. 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 :)

username too short

submitFunc 是一个持有提交按钮函数或 null 的 observable,因为 Dart 中的函数实际上是对象,这很好。 null 值初始分配将禁用按钮。

onInit

debounce 工作线程在更改 validations 可观察端 500 毫秒后调用 username 函数。

validations 将接收 username.value 作为其参数。

More on workers

验证

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;
    };
  }

答案 1 :(得分:1)

在这里看看

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
    );
  }
}

答案 2 :(得分:0)

GetX并不能解决所有问题,但是它具有一些实用程序方法可以帮助您实现所需的目标。例如,您可以将validatorSnackBar一起使用进行最终检查。这是一个代码段,可以帮助您了解基础知识。

TextFormField(
  controller: emailController,
  autovalidateMode: AutovalidateMode.onUserInteraction,
  validator: (value) {
    if (!GetUtils.isEmail(value))
      return "Email is not valid";
    else
      return null;
  },               
),

GetUtils几乎没有用于快速验证的便捷方法,您将不得不探索每种方法以查看其是否适合您的需求。