首页 > 解决方案 > 为什么点击提交时 Flutter 表单会重置所有字段?

问题描述

我有一个FORMwithe 32TEXTFORMFIELDS和一个按钮来验证和导航到输出屏幕。

TextButton(
              onPressed: () {
                _formKey.currentState.save(); // I added this line which does nothing
                if (_formKey.currentState.validate()) {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                      builder: (context) {
                        return OutputScreen();
                      },
                    ),
                  );
                } else {
                  _showAlert(context); // third partypackage alert function
                }
              },
              child: Text(
                'Calculate',
              ),
            ),

我的问题是,如果用户单击提交,有时它会重置所有字段,无论验证是真还是假;

这是我经过大量测试后发现的一个东西,当用户输入一个文本字段时,输入键盘有一个“DONE”键,用户可以使用它来结束编辑。现在,如果用户没有使用它并且只是点击下一个字段进行输入并继续单击我创建的 subit 按钮,它会重置所有表单。

有任何想法吗?或者有没有办法强制用户在完成输入后点击键盘上的“完成”。

提前致谢。

///////////////////////////////////////// / 编辑:完整代码示例 ///////////////////////////////////// ///////

class CementInputPage extends StatefulWidget {
  @override
  _CementInputPageState createState() => _CementInputPageState();
}

class _CementInputPageState extends State<CementInputPage> {
  static const double sizedBoxHeight = 8;
  final _formKeyCement = GlobalKey<FormState>();
  CementData cementData = new CementData();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Color(0xFFDDDDDD),
      appBar: AppBar(
        title: Text("Cement Input Data"),
      ),
      body: SafeArea(
        child: Form(
          key: _formKeyCement,
          child: ListView(
            children: [
              // Header data
              WhiteBoxContainer( //container I created in another file
                boxTitle: 'Header',
                childWidget: Column(
                  children: [
                    //TODO: Validate date format
                    myStringTextInputRow('Date'),
                    SizedBox(height: sizedBoxHeight),
                    myStringTextInputRow('Operator Company'),
                    SizedBox(height: sizedBoxHeight),
                    myStringTextInputRow('Cement Contractor'),
                    SizedBox(height: sizedBoxHeight),
                    myStringTextInputRow('Well Name'),
                    SizedBox(height: sizedBoxHeight),
                    myStringTextInputRow('Field Name'),
                    SizedBox(height: sizedBoxHeight),
                    myStringTextInputRow('Rig'),
                    SizedBox(height: sizedBoxHeight),
                    myStringTextInputRow('Rig Supervisor'),
                    SizedBox(height: sizedBoxHeight),
                    myStringTextInputRow('Cement Supervisor'),
                    SizedBox(height: sizedBoxHeight),
                  ],
                ),
              ),
              //
              //Well data
              WhiteBoxContainer(
                boxTitle: 'Well Data',
                childWidget: Column(
                  children: [
                    Row(
                      children: [
                        Expanded(
                          child: TextFormField(
                            keyboardType:
                                TextInputType.numberWithOptions(decimal: true),
                            autovalidateMode:
                                AutovalidateMode.onUserInteraction,
                            decoration: InputDecoration(
                              border: OutlineInputBorder(),
                              labelText: "Section Depth (ft)",
                            ),
                            validator: (value) {
                              return sectionTDValidator(value);
                            },
                          ),
                        ),
                        checkInputStatus(InputValidationStatus.notValid),
                      ],
                    ),
                    SizedBox(height: sizedBoxHeight),
                    Row(
                      children: [
                        Expanded(
                          child: TextFormField(
                            keyboardType:
                                TextInputType.numberWithOptions(decimal: true),
                            autovalidateMode:
                                AutovalidateMode.onUserInteraction,
                            decoration: InputDecoration(
                              border: OutlineInputBorder(),
                              labelText: "Casing length (ft)",
                            ),
                            validator: (value) {
                              return casingLengthValidator(value);
                            },
                          ),
                        ),
                        checkInputStatus(InputValidationStatus.notValid),
                      ],
                    ),
              Container(
                child: TextButton(
                  onPressed: () {
                    _formKeyCement.currentState.save(); // line I added which did nothing
                    if (_formKeyCement.currentState.validate()) {
                      Navigator.push(
                        context,
                        MaterialPageRoute(
                          builder: (context) {
                            return CementOutputScreen();
                          },
                        ),
                      );
                    } else {
                     //I want to show an alert dialog   
                  child: Text(
                    'Calculate',
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }

    String sectionTDValidator(String value) {
    if (value.isNotEmpty) {
      cementData.sectionTD = double.parse(value);
      if (cementData.sectionTD < kMinWellDepth) {
        return 'Section Depth is too short!';
      } else if (cementData.sectionTD > kMaxWellDepth) {
        return 'Section depth is too long!';
      } else if (cementData.casingLength != null &&
          cementData.casingLength > cementData.sectionTD) {
        return 'Section depth is shorter than casing length!';
      }
    } else {
      cementData.sectionTD = null;
    }
    return null;
  }

  String casingLengthValidator(String value) {
    if (value.isNotEmpty) {
      cementData.casingLength = double.parse(value);
      if (cementData.casingLength < kMinWellDepth) {
        return 'Casing Length is too short!';
      } else if (cementData.casingLength > kMaxWellDepth) {
        return 'Casing Length is too long!';
      } else if (cementData.sectionTD != null &&
          cementData.casingLength > cementData.sectionTD) {
        return 'Casing Length is longer than section depth!';
      } else if (cementData.leadLength != null) {

        if (cementData.leadLength > cementData.casingLength) {
          return 'Casing length is shorter than lead length!';
        } else if (cementData.tailLength != null) {
          // check tail length
          if (cementData.tailLength > cementData.casingLength) {
            return 'Casing length is shorter than lead length!';
          } else if ((cementData.leadLength + cementData.tailLength) >
              cementData.casingLength) {
            return 'Casing length is shorter than total cement length!';
          }
        }
      } else if (cementData.shoeTrackLength != null &&
          cementData.shoeTrackLength >= cementData.casingLength) {
        return 'Shoe track length is >= casing length!';
      }
    } else {
      cementData.casingLength = null;
    }
    return null;
  }

  String shoeTrackLengthValidator(String value) {
    if (value.isNotEmpty) {
      cementData.shoeTrackLength = double.parse(value);
      if (cementData.casingLength != null &&
          cementData.shoeTrackLength >= cementData.casingLength) {
        return 'Shoe track length is >= casing length!';
      }
    } else {
      cementData.shoeTrackLength = null;
    }
    return null;
  }

  String stickUpLengthValidator(String value) {
    if (value.isNotEmpty) {
      cementData.stickUpLength = double.parse(value);
      if (cementData.stickUpLength > kMaxStickUpLength) {
        return 'Stick up length is too long!';
      }
    } else {
      cementData.stickUpLength = null;
    }
    return null;
  }
}

Row myStringTextInputRow(String labelText) {
  return Row(
    children: [
      Expanded(
        child: TextFormField(
          keyboardType: TextInputType.name,
          maxLines: 2,
          minLines: 1,
          decoration: InputDecoration(
            border: OutlineInputBorder(),
            labelText: labelText,
          ),
        ),
      ),
      checkInputStatus(InputValidationStatus.notCritical),
    ],
  );
}

Container checkInputStatus(InputValidationStatus inputStatus) {
  if (inputStatus == InputValidationStatus.notValid) {
    return Container(
      alignment: Alignment.centerLeft,
      padding: EdgeInsets.only(left: 3),
      child: Icon(
        Icons.clear,
        color: Colors.red[900],
        size: 18.0,
        semanticLabel: 'Feedback icon',
      ),
    );
  } else if (inputStatus == InputValidationStatus.valid) {
    return Container(
      alignment: Alignment.centerLeft,
      padding: EdgeInsets.only(left: 3),
      child: Icon(
        Icons.done,
        color: Colors.green[900],
        size: 18.0,
        semanticLabel: 'Feedback icon',
      ),
    );
  } else {
    return Container(
      alignment: Alignment.centerLeft,
      padding: EdgeInsets.only(left: 3),
      child: Icon(
        Icons.flaky,
        color: Colors.orange[700],
        size: 18.0,
        semanticLabel: 'Feedback icon',
      ),
    );
  }
  ;
}

标签: formsfluttervalidationdartflutter-test

解决方案


尝试添加TextEditingController到您TextFormField的 s 并删除autovalidateMode.


推荐阅读