Dart 颤振步进程序小部件-在各个步骤中验证字段

Dart 颤振步进程序小部件-在各个步骤中验证字段,dart,flutter,stepper,Dart,Flutter,Stepper,我使用stepper小部件来收集用户的信息并进行验证,我需要在每个步骤调用API,从而在每个继续按钮的步骤中验证每个字段。。。我正在使用表单状态和表单小部件,但问题是它在stepper的所有步骤中验证整个字段。。。如何仅验证步进机中的单个步骤?我在Stepper.dart中浏览了Stepper和State类中的文档,但没有支持函数 下面是代码 class SubmitPayment extends StatefulWidget { SubmitPayment({Key key, this.

我使用stepper小部件来收集用户的信息并进行验证,我需要在每个步骤调用API,从而在每个继续按钮的步骤中验证每个字段。。。我正在使用表单状态和表单小部件,但问题是它在stepper的所有步骤中验证整个字段。。。如何仅验证步进机中的单个步骤?我在Stepper.dart中浏览了Stepper和State类中的文档,但没有支持函数

下面是代码

class SubmitPayment extends StatefulWidget {


 SubmitPayment({Key key, this.identifier, this.amount, this.onResendPressed})
      : super(key: key);

  final String identifier;
  final String amount;
  final VoidCallback onResendPressed;

  @override
  State<StatefulWidget> createState() {
    return _SubmitPaymentState();
  }
}

class _SubmitPaymentState extends State<SubmitPayment> {
  final GlobalKey<FormState> _formKeyOtp = GlobalKey<FormState>();
  final FocusNode _otpFocusNode = FocusNode();
  final TextEditingController _otpController = TextEditingController();
  bool _isOTPRequired = false;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 8.0),
      child: Form(
          key: _formKeyOtp,
          child: Column(children: <Widget>[
            Center(
                child: Padding(
                    padding:
                        EdgeInsets.symmetric(horizontal: 16.0, vertical: 5.0),
                    child: Text(
                      Translations.of(context).helpLabelOTP,
                      style: TextStyle(
                          color: Theme.of(context).primaryColor,
                          fontStyle: FontStyle.italic),
                    ))),
            CustomTextField(
              icon: Icons.vpn_key,
              focusNode: _otpFocusNode,
              hintText: Translations.of(context).otp,
              labelText: Translations.of(context).otp,
              controller: _otpController,
              keyboardType: TextInputType.number,
              hasError: _isOTPRequired,
              validator: (String t) => _validateOTP(t),
              maxLength: AppConstants.otpLength,
              obscureText: true,
            ),
            Center(
                child: ButtonBar(
              mainAxisSize: MainAxisSize.max,
              alignment: MainAxisAlignment.center,
              children: <Widget>[
                RaisedButton(
                  child: Text(Translations.of(context).resendOtpButton),
                  color: Colors.white,
                  textColor: Theme.of(context).primaryColor,
                  onPressed: widget.onResendPressed,
                ),
                RaisedButton(
                  child: Text(
                    Translations.of(context).payButton,
                  ),
                  onPressed: _doPullPayment,
                ),
              ],
            )),
          ])),
    );
  }

  String _validateOTP(String value) {
    if (value.isEmpty || value.length < AppConstants.otpLength) {
      setState(() => _isOTPRequired = true);
      return Translations.of(context).invalidOtp;
    }
    return "";
  }

  bool _validateOtpForm() {
    _formKeyOtp.currentState.save();
    return this._formKeyOtp.currentState.validate();
  }

  Future<void> _doPullPayment() async {
    setState(() {
      _isOTPRequired = false;
    });

    if (!_validateOtpForm()) return false;

    try {
      setState(() {
        _isOTPRequired = false;
      });
      showDialog(
        barrierDismissible: false,
        context: context,
        builder: (context) => AlertDialog(
              content: ListTile(
                leading: CircularProgressIndicator(),
                title: Text(Translations.of(context).processingPaymentDialog),
              ),
            ),
      );

      TransactionApi api =
          TransactionApi(httpDataSource, authenticator.sessionToken);
      String responseMessage = await api.doPullPayment(
          widget.identifier,
          widget.amount,
          _otpController.text,
          TransactionConstants.transactionCurrency);

      Navigator.of(context).pop();
      await showAlertDialog(
          context, Translations.of(context).pullPayment, '$responseMessage');
      Navigator.pop(context);
    } catch (exception) {
      await showAlertDialog(context, Translations.of(context).pullPayment,
          '${exception.message}');
      Navigator.of(context).pop();
    }
  }
class SubmitPayment扩展了StatefulWidget{
SubmitPayment({Key Key,this.identifier,this.amount,this.onResendPressed})
:super(key:key);
最终字符串标识符;
最终字符串金额;
按重新发送时的最终作废回调;
@凌驾
状态createState(){
返回_SubmitPaymentState();
}
}
类_SubmitPaymentState扩展状态{
最终GlobalKey _formKeyOtp=GlobalKey();
最终焦点节点_otpFocusNode=FocusNode();
最终文本编辑控制器_otpController=文本编辑控制器();
bool_isoprequired=false;
@凌驾
小部件构建(构建上下文){
返回填充(
填充:仅限常量边集(顶部:8.0),
孩子:表格(
密钥:_formKeyOtp,
子项:列(子项:[
居中(
孩子:填充(
衬垫:
边缘组。对称(水平:16.0,垂直:5.0),
子:文本(
翻译(上下文).helpLabelOTP,
样式:TextStyle(
颜色:主题。背景。原色,
fontStyle:fontStyle.italic),
))),
自定义文本字段(
图标:Icons.vpn_键,
焦点节点:_otpFocusNode,
hintText:Translations.of(context).otp,
labelText:Translations.of(context).otp,
控制器:\ OTP控制器,
键盘类型:TextInputType.number,
hasError:_等要求,
验证器:(字符串t)=>\u validateOTP(t),
maxLength:AppConstants.otpLength,
蒙昧文字:对,
),
居中(
孩子:巴顿巴(
mainAxisSize:mainAxisSize.max,
对齐:MainAxisAlignment.center,
儿童:[
升起的按钮(
子:文本(Translations.of(context).resendtpbutton),
颜色:颜色,白色,
textColor:Theme.of(context.primaryColor),
onPressed:widget.onResendPressed,
),
升起的按钮(
子:文本(
翻译(上下文).payButton,
),
按下按钮:_doPullPayment,
),
],
)),
])),
);
}
字符串_validateOTP(字符串值){
if(value.isEmpty | value.length_isOTPRequired=true);
返回翻译.of(context).invalidOtp;
}
返回“”;
}
bool_validateOtpForm(){
_formKeyOtp.currentState.save();
返回此项。_formKeyOtp.currentState.validate();
}
Future\u doPullPayment()异步{
设置状态(){
_isOTPRequired=假;
});
如果(!\u validateOtpForm())返回false;
试一试{
设置状态(){
_isOTPRequired=假;
});
显示对话框(
禁止:错误,
上下文:上下文,
生成器:(上下文)=>AlertDialog(
内容:ListTile(
前导:CircularProgressIndicator(),
标题:文本(翻译).of(上下文).processingPaymentDialog),
),
),
);
TransactionApi api=
TransactionApi(httpDataSource,authenticator.sessionToken);
String responseMessage=等待api.doPullPayment(
widget.identifier,
金额,
_otpController.text,
TransactionConstants.transactionCurrency);
Navigator.of(context.pop();
等待显示警报对话框(
(context.pullPayment,“$responseMessage”);
Navigator.pop(上下文);
}捕获(例外){
等待showAlertDialog(上下文,翻译)(上下文).pullPayment,
“${exception.message}”);
Navigator.of(context.pop();
}
}

为每个步骤使用一个单独的
表单。使用一个可以基于
\u currentStep
索引的
GlobalKey
列表,然后在
onStepContinue
中调用
验证()

List<GlobalKey<FormState>> _formKeys = [GlobalKey<FormState>(), GlobalKey<FormState>(), …];
…

Stepper(
  currentStep: _currentStep,
  onStepContinue: () {
    setState(() {
      if (_formKeys[_currentStep].currentState.validate()) {
        _currentStep++;
      }
    });
  },
  steps: 
  Step(
    child: Form(key: _formKeys[0], child: …),
List_formKeys=[GlobalKey(),GlobalKey(),…];
…
步进机(
currentStep:_currentStep,
onStepContinue:(){
设置状态(){
if(_formKeys[_currentStep].currentState.validate()){
_currentStep++;
}
});
},
步骤:
台阶(
子项:窗体(键:_formKeys[0],子项:…),

显然,您需要检查最后一步并保存,而不是在最后验证:)

所以我解决了这个问题,如下所示:

问题是,如果my逻辑有效,我返回的是一个*空字符串(“”*,其中FormState的asvalidate方法要求与TextFormField关联的每个验证器方法在验证通过时返回null

我改变了主意

 String _validateOTP(String value) {
    if (value.isEmpty || value.length < AppConstants.otpLength) {
      setState(() => _isOTPRequired = true);
      return Translations.of(context).invalidOtp;
    }
    return "";
  }
String\u validateOTP(字符串值){
if(value.isEmpty | value.length_isOTPRequired=true);
返回翻译.of(context).invalidOtp;
}
返回“”;
}

String\u validateOTP(字符串值){
if(value.isEmpty | value.length_isOTPRequired=true);
返回翻译.of(context).invalidOtp;
}
返回null;
}

String _validateOTP(String value) { if (value.isEmpty || value.length < AppConstants.otpLength) { setState(() => _isOTPRequired = true); return Translations.of(context).invalidOtp; } return null;