У меня 3 виджета.

HomeApp - виджет без сохранения состояния, который связывает все.
Пользовательский виджет AppBarWidget - виджет с отслеживанием состояния, у которого есть кнопка отправки.
Виджет SurveyForm - виджет с отслеживанием состояния, который имеет более 50 входов, включая TextFormField, переключатели и целую кучу настраиваемых типов ввода.

Когда пользователь нажимает кнопку отправки на панели приложений, ему необходимо выполнить некоторые пользовательские проверки в форме опроса, создать новый класс модели. которые переводятся в объект JSON и передают POST в API.

Я прочитал несколько вариантов,

  1. Запустите все переменные и логику проверки / отправки в HomeApp, передайте ее в SurveyForm и используйте обратный вызов для запуска функции. Но это включает в себя передачу более 50 параметров в SurveyForm.
  2. Использование GlobalKey. Не совсем уверен, как это работает. Когда я пытаюсь сделать final key = new GlobalKey<SurveyForm>();, он сказал 'SurveyForm' doesn't extend 'State<StatefulWidget>'..
  3. Передайте родительский экземпляр дочернему виджету, предложенному эту ссылку.
  4. Вызов метода дочернего виджета, но по этой ссылке сказано, что это не рекомендуется.
  5. Напишите собственный контроллер.

Что было бы предпочтительнее во Flutter?

0
hook38 2 Сен 2020 в 17:16

2 ответа

Лучший ответ

Так что мне удалось это решить. Моя проблема должна быть разбита на 3 задачи.

  1. Проверить текстовое поле, переключатели, все настраиваемые поля ввода.
  2. Создайте новый класс модели, который можно передать в формате JSON.
  3. Отправьте форму с помощью кнопки в другом виджете (панели приложений).

Чтобы решить первую, я обернул все в SurveyForm в виджет формы. Эта часть проста, в Интернете есть множество руководств. Чтобы выполнить проверку пользовательских входных данных, я заключил их в виджет FormField и запустил метод didChange для FormFieldState. Это позволяет мне использовать методы validator и onSaved для FormField с помощью методов callback. Ниже мой рабочий код для datepicker.

class Q1<T> extends StatefulWidget {
  final FormFieldValidator<DateTime> validator;
  final FormFieldSetter<DateTime> onSaved;

  const Q1({
    Key key,
    @required this.onSaved,
    @required this.validator,
  })  : assert(validator != null),
        assert(onSaved != null),
        super(
          key: key,
        );

  @override
  _Q1State createState() => _Q1State();
}

class _Q1State extends State<Q1> {
  DateTime _completionDate;

  @override
  Widget build(BuildContext context) {
    return FormField(
      validator: (val) {
        return widget.validator(val);
      },
      onSaved: (val) {
        widget.onSaved(val);
      },
      builder: (FormFieldState<dynamic> field) {
        return Row(
          children: [
            Expanded(
              flex: 1,
              child: Text('1. Completion Date'),
            ),
            Expanded(
              flex: 2,
              child: Row(
                children: [
                  Container(
                    padding: EdgeInsets.all(
                      SizeConfig().getProportionateScreenWidth(
                          kDatePickerIconTextBoxPadding),
                    ),
                    decoration: BoxDecoration(
                      border: Border.all(
                        color: kDatePickerIconTextBoxBorderColor,
                      ),
                      borderRadius: BorderRadius.all(Radius.circular(
                        SizeConfig().getProportionateScreenWidth(
                            kDatePickerIconTextBoxRadius),
                      ) //         <--- border radius here
                          ),
                    ),
                    child: Text(_completionDate == null
                        ? 'Pick a date'
                        : DateFormat(kDateFormat).format(_completionDate)),
                  ),
                  IconButton(
                      onPressed: () {
                        showDatePicker(
                          context: context,
                          initialDate: DateTime.now(),
                          firstDate: DateTime(2000),
                          lastDate: DateTime(2100),
                        ).then((date) {
                          setState(() {
                            field.didChange(date);
                            _completionDate = date;
                          });
                        });
                      },
                      icon: FaIcon(FontAwesomeIcons.calendarAlt)),
                ],
              ),
            ),
          ],
        );
      },
    );
  }
}

И я только что вызвал виджет с

Q1(
              validator: (val) {
                if (val == null) {
                  return 'Completion Date is missing';
                }
                return null;
              },
              onSaved: (value) {
                setState(() {
                  widget.questionnaire.completion_date = DateFormat(kDateFormat).format(value);
                });
              },
            ),

Чтобы решить второй. Я использовал json_serializable, где объект также можно передавать между HomeApp и виджетом SurveyForm, поэтому мне не нужно передавать около 50+ переменных.

А для третьей проблемы я инициировал final _formKey = GlobalKey<FormState>(); в HomeApp, передал его виджету SurveyForm и использовал обратный вызов onPressed на панели приложений для запуска проверки / отправки в SurveyForm.

Bloc будет использоваться для отправки JSON и загрузки анимации, но не только.

Я новичок в флаттере (использую это в течение месяца), дайте мне знать, есть ли у кого-нибудь лучшее решение.

0
hook38 3 Сен 2020 в 15:49

Вы можете использовать виджет формы Учебное пособие. В основном вы оборачиваете все свои текстовые поля, флажки и другие вещи с помощью виджета формы и устанавливаете его ключ на GlobalKey<FormState>(). теперь вы можете использовать в нем другой тип полей (например, вместо TextaField вы используете TextFormField); теперь вы можете установить для них свойство onSaved (мы будем использовать его немного позже). затем всякий раз, когда вы хотите отправить данные формы, вы вызываете функцию, которую вы написали в своем классе состояния (добавляя ее к значению onPressed кнопки). Это примерно так:

void _submitForm() {
    final form = _formKey.currentState; // this is your GlobalKey<FormState> that you specified and set to the key of your Form Widget.
    if (form.validate()) { // form.validate() will call all the validator functions that you've passed to your inputfields
      form.save(); // This will call all the onSaved functions that you passed to your forms.
    }
}

Он получает ваш виджет формы, вызывает все функции валидатора входных данных, если все совпадает, вызывает все функции входов onSaved.

Вы можете создать словарь и в onSaved из полей ввода установить в нем входные значения. Теперь вы можете использовать json.encode(your_data_dict), чтобы преобразовать его в строку JSON или использовать свой объект. затем опубликуйте файл json.

0
Parsa 2 Сен 2020 в 14:52