Проверка форм Flutter getX

#forms #flutter #validation #flutter-getx #flutter-form-builder

#формы #флаттер #проверка #flutter-getx #flutter-конструктор форм

Вопрос:

Я ищу пример того, как наилучшим образом обрабатывать формы и валидацию с помощью getX? Есть ли какой-нибудь хороший пример этого или кто-нибудь может показать мне пример того, как мы лучше всего можем это сделать?

Комментарии:

1. вы можете увидеть расширение getx для vs code. В нем есть несколько фрагментов для getx, а также getx forms. marketplace.visualstudio.com /…

Ответ №1:

Вот пример того, как вы могли бы использовать наблюдаемые getX для динамического обновления полей формы и кнопки отправки.

Я не утверждаю, что это лучшая практика. Я уверен, что есть лучшие способы сделать то же самое. Но интересно поиграть с тем, как getX можно использовать для выполнения проверки.

Форма Obx

Два представляющих интерес виджета, которые перестраиваются на основе наблюдаемых изменений значений:

  1. TextFormField
    • errorText Изменения InputDecoration и перестроят этот виджет
    • onChanged: fx.usernameChanged не вызывает перестроек. Это вызывает функцию в контроллере usernameChanged(String val) при изменении ввода поля формы.
    • Он просто обновляет username наблюдаемое новым значением.
    • Может быть записано как:
    • onChanged: (val) => fx.username.value = val
  2. ElevatedButton (кнопка «Отправить»)
    • onPressed функция может переключаться между null и функцией
    • null отключает кнопку (единственный способ сделать это в Flutter)
    • функция здесь активирует кнопку
 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
                ),
              )
            ],
          ),
        ),
      ),
    );
  }
}
  

Контроллер getX

Объяснение / разбивка ниже

 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) amp;amp; 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 будет отображаться красным цветом, что означает недопустимый ввод. Когда в поле вводится недопустимый ввод, мы показываем сообщение об ошибке. ( min. 5 chars в примере:)

слишком короткое имя пользователя

submitFunc является наблюдаемым для удержания функции кнопки отправки или null , поскольку функции в Dart на самом деле являются объектами, это нормально. Первоначальное null присвоение значения отключит кнопку.

OnInit

debounce Рабочий вызывает validations функцию через 500 мс после внесения изменений в username наблюдаемый конец.

validations получит username.value в качестве своего аргумента.

Подробнее о рабочих.

Проверки

Внутри validations функции мы помещаем любые типы проверки, которые мы хотим выполнить: минимальная длина, плохие символы, имя, которое уже занято, имена, которые нам лично не нравятся из-за детских хулиганов и т. Д.

Для дополнительного реализма available() функция async . Обычно при этом запрашивается база данных для проверки доступности имени пользователя, поэтому в этом примере перед возвратом этой проверки проверки возникает ложная задержка в 1 секунду.

submitFunction() возвращает функцию, которая заменит нулевое значение в submitFunc observable, когда мы убедимся, что форма имеет допустимые входные данные, и мы разрешаем пользователю продолжить.

Мы бы попробовали быть немного более реалистичными. ожидайте некоторого возвращаемого значения от функции кнопки отправки, чтобы мы могли заставить функцию кнопки возвращать будущий 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;
    };
  }
  

Ответ №2:

getX — это не решение для всего, но у него есть несколько полезных методов, которые могут помочь вам достичь того, чего вы хотите. Например, вы можете использовать a validator вместе с SnackBar для окончательной проверки. Вот фрагмент кода, который может помочь вам понять основы.

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

GetUtils имеет несколько удобных методов для быстрой проверки, и вам нужно будет изучить каждый метод, чтобы увидеть, соответствует ли он вашим потребностям.

Комментарии:

1. Потрясающий комментарий, использование GetUtils и autovalidatemode упрощает задачу!!