首页 > 解决方案 > Flutter FormField Validator 验证失败

问题描述

我尝试通过使用 FormField 包装来创建自定义 TextField。它按我想要的方式工作得很好.. 直到我尝试多次使用它的实例.. 例如,我创建了 InputTextField,所以每当我想多次使用它时,例如全名、电子邮件和电话号码。它会返回错误。但是当我使用它一次或注释掉 InputTextWidget 的 3 个验证器函数中的 2 个时。它会运作良好。

错误消息:在 null 上调用了 getter 'isEmpty'。接收方:null 尝试调用:isEmpty

我的代码片段如下

class InputTextWidget extends StatelessWidget {
  final String hintText;
  final TextInputType keyboardType;
  final TextInputAction keyboardAction;
  final TextEditingController inputController;
  final double height;
  final FormFieldValidator<String> validator;

  const InputTextWidget(
      {Key key,
      @required this.hintText,
      @required this.keyboardType,
      @required this.keyboardAction,
      @required this.inputController,
      this.validator,
      this.height = 50})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FormField(
        validator: validator,
        builder: (FormFieldState formFieldState) {
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Container(
                height: height,
                width: double.maxFinite,
                decoration: BoxDecoration(
                  border: Border.all(
                    color: AppColors.inputBorderColor,
                  ),
                  borderRadius: BorderRadius.all(
                    Radius.circular(8),
                  ),
                ),
                child: TextFormField(
                  // Notify the FormField State of Changes
                  onChanged: (String value) {
                    formFieldState.didChange(value);
                  },
                  controller: inputController,
                  style: TextStyle(fontSize: 14),
                  keyboardType: keyboardType,
                  textInputAction: keyboardAction,
                  decoration:
                      InputDecoration.collapsed(hintText: hintText).copyWith(
                    hasFloatingPlaceholder: false,
                    contentPadding: EdgeInsets.symmetric(
                      vertical: 15,
                      horizontal: 10,
                    ),
                  ),
                ),
              ),
              // Show Form Field Error
              _showError(formFieldState),
            ],
          );
        });
  }

  Widget _showError(FormFieldState formFieldState) {
    if (formFieldState.hasError)
      return Padding(
        padding: EdgeInsets.only(left: 8.0, top: 5),
        child: Text(
          formFieldState.errorText,
          style: TextStyle(
            color: AppColors.errorColor,
            fontWeight: FontWeight.w500,
            fontSize: 10,
          ),
        ),
      );
    return SizedBox();
  }
}

我在表单中使用自定义验证器的地方。

         Form(
              autovalidate: true,
              key: formKey,
              child: Column(
                children: [
                  InputTextWidget(
                    hintText: "full Name",
                    keyboardType: TextInputType.text,
                    keyboardAction: null,
                    inputController: _fullName,
                    validator: (value) {
                      if (value.isEmpty) return "Full Name field is required";
                      return null;
                    },
                  ),
                  SizedBox(height: 20),
                  InputTextWidget(
                    hintText: "Email Address",
                    keyboardType: TextInputType.emailAddress,
                    keyboardAction: null,
                    inputController: _email,
                    validator: (String value) {
                      if (value.isEmpty) return "Email field is required";
                      if (!FormValidator.isValidateEmail(value))
                        return "Invalid email address";
                      return null;
                    },
                  ),
                  SizedBox(height: 20),
                  InputTextWidget(
                    hintText: "Phone Number",
                    keyboardType: TextInputType.phone,
                    keyboardAction: null,
                    inputController: _phoneNumber,
                    validator: (String value) {
                      if (value.isEmpty)
                        return "Phone Number field is required";
                      if (!FormValidator.isValidPhoneNumber(value))
                        return "Invalid Phone Number";
                      return null;
                    },
                  ),
                ],
              ),
            ),

标签: androidiosflutterflutter-layout

解决方案


validator你在小部件构建时执行的FormField,一个小技巧将是使用该validator属性来TextFormField代替。


以您的代码为例添加了一个演示:

class InputTextWidget extends StatelessWidget {
  final String hintText;
  final TextInputType keyboardType;
  final TextInputAction keyboardAction;
  final TextEditingController inputController;
  final double height;
  final FormFieldValidator<String> validator;

  const InputTextWidget(
      {Key key,
      @required this.hintText,
      @required this.keyboardType,
      @required this.keyboardAction,
      @required this.inputController,
      this.validator,
      this.height = 50})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FormField(
      builder: (FormFieldState formFieldState) {
        return Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Container(
              height: height,
              width: double.maxFinite,
              decoration: BoxDecoration(
                border: Border.all(),
                borderRadius: BorderRadius.all(
                  Radius.circular(8),
                ),
              ),
              child: TextFormField(
                // new line
                validator: validator, // use validator in [TextFormField]
                // Notify the FormField State of Changes
                onChanged: (String value) {
                  formFieldState.didChange(value);
                },
                controller: inputController,
                style: TextStyle(fontSize: 14),
                keyboardType: keyboardType,
                textInputAction: keyboardAction,
                decoration:
                    InputDecoration.collapsed(hintText: hintText).copyWith(
                  hasFloatingPlaceholder: false,
                  contentPadding: EdgeInsets.symmetric(
                    vertical: 15,
                    horizontal: 10,
                  ),
                ),
              ),
            ),
            // Show Form Field Error
            _showError(formFieldState),
          ],
        );
      },
    );
  }

推荐阅读