首页 > 解决方案 > 如何在颤动中验证动态创建的表单?

问题描述

我目前正在动态创建一个自定义表单小部件(行),并且想知道验证每个表单的最佳方法是什么。通过尝试使用全局 FormState 键,没有任何作用,因为每个表单实例都共享该键(我假设)。

这会产生问题,例如键盘在专注于文本字段时会立即退出。

想知道是否有人对此有解决方案或可以指出我正确的方向。谢谢!

根小部件:

class ExerciseTable extends ConsumerWidget {
  final Exercise exercise;
  ExerciseTable({@required this.exercise});

  @override
  Widget build(BuildContext context, ScopedReader watch) {
    final _exerciseTableController = watch(exerciseTableControllerProvider);

    /*
    * Logic of where I build the form rows dynamically
    */
    List<Widget> _buildFormRows() {
      List<Widget> rows = [];
      int sets = int.parse(exercise.sets);
      for (int i = 1; i < sets; i++) {
        rows.add(
          _BuildExerciseRow(
            set: i.toString(),
          ),
        );
      }
      return rows;
    }

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          exercise.exerciseName,
          style: Theme.of(context).textTheme.headline6,
        ),
        const SizedBox(height: 8),
        YoutubePlayerTile(
          url: exercise.exerciseURL,
        ),
        const SizedBox(height: 8),
        _BuildRowHeader(),
        Column(children: _buildFormRows())
      ],
    );
  }
}

单个表单行小部件:

/**
 * * Form Rows
 */
class _BuildExerciseRow extends StatelessWidget {
  final String set;
  final _formKey = GlobalKey<FormState>();
  final _kgTextEditingController = TextEditingController();
  final _repsTextEditingController = TextEditingController();
  _BuildExerciseRow({this.set});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: EdgeInsets.symmetric(horizontal: 5),
      child: Form(
        key: _formKey,
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          crossAxisAlignment: CrossAxisAlignment.center,
          mainAxisSize: MainAxisSize.max,
          children: [
            Text(set),
            const SizedBox(width: 15),
            Text("-"),
            const SizedBox(width: 15),
            _BuildInputTextField(
                controller: _kgTextEditingController,
                validator: (value) {
                  if (value.isEmpty) {
                    return "Please enter some text";
                  } else
                    return "";
                }),
            // const SizedBox(width: 15),
            _BuildInputTextField(
              controller: _repsTextEditingController,
            ),
            TickBox(onTap: () => _formKey.currentState.validate())
          ],
        ),
      ),
    );
  }
}

class _BuildInputTextField extends StatelessWidget {
  // final int keyValue;
  final String Function(String) validator;
  final TextEditingController controller;
  _BuildInputTextField({this.validator, @required this.controller});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 2),
      height: 39,
      width: 80,
      child: TextFormField(
          validator: validator,
          inputFormatters: [
            LengthLimitingTextInputFormatter(6),
          ],
          controller: controller,
          keyboardType: TextInputType.number,
          decoration: InputDecoration(
            contentPadding: const EdgeInsets.only(bottom: 5, left: 10),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(width: 1),
            ),
          ),
          onChanged: (value) => {}),
    );
  }
}

自定义 TextFormField 小部件:

class _BuildInputTextField extends StatelessWidget {
  // final int keyValue;
  final String Function(String) validator;
  final TextEditingController controller;
  _BuildInputTextField({this.validator, @required this.controller});

  @override
  Widget build(BuildContext context) {
    return Container(
      padding: const EdgeInsets.symmetric(vertical: 2),
      height: 39,
      width: 80,
      child: TextFormField(
          validator: validator,
          inputFormatters: [
            LengthLimitingTextInputFormatter(6),
          ],
          controller: controller,
          keyboardType: TextInputType.number,
          decoration: InputDecoration(
            contentPadding: const EdgeInsets.only(bottom: 5, left: 10),
            border: OutlineInputBorder(
              borderRadius: BorderRadius.circular(8),
              borderSide: BorderSide(width: 1),
            ),
          ),
          onChanged: (value) => {}),
    );
  }
}

标签: flutterdart

解决方案


尝试将您的validator回调更改为

validator: (value) {
                  if (value.isEmpty) {
                    return "Please enter some text";
                  } else
                    return null;
                }),

推荐阅读